'Proper way to detect if SQLCMD.exe is installed?
I am creating a class library that takes .SQL files as input (FileInfo) and a connection string. It then attempts to execute the sql file against the connection.
I have decided to support Microsoft's SMO and SQLCMD.exe
In testing, I have noticed on many machines in my environment, that SQLCMD does not come installed by default. My program errors when just attempting to run the process SQLCMD.exe.
What is the proper way to look for it without searching the entire hard drive? Is there a common registry location that specifies if it is installed? Usually when it is installed, I think a PATH location is set.
Many thanks.
Solution 1:[1]
I have a 64 machine with 64 bit SQL SERVER (2k8 R2) and my SQLCMD.EXE is in c:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE
.
It's also in the path.
You could just look for the path directly from the SQL Server Registry location:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\100\Tools\ClientSetup\path
Or a variant on this for a different version.
The big issue here is that SQLCMD is part of the client tools, not the SQL Server so I reckon you cannot ask SQL Server to tell you. Unless of course you're running on the server itself.
Solution 2:[2]
Start cmd.exe and use
where sqlcmd.exe
Solution 3:[3]
Here's a solution - using execute process.
It works for all install variants of MS SQL
(with 100-170)
function ExecuteProcess(const FileName, Params: string;
Folder: string; WaitUntilTerminated, WaitUntilIdle, RunMinimized: Boolean;
var ErrorCode: Integer): Boolean;
var
cmdLine: string;
WorkingDirP: PChar;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
Result := true;
cmdLine := '"' + FileName + '" ' + Params;
if Folder = '' then
Folder := ExcludeTrailingPathDelimiter(ExtractFilePath(FileName));
ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
StartupInfo.cb := SizeOf(StartupInfo);
if RunMinimized then
begin
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
end;
if Folder <> '' then
WorkingDirP := PChar(Folder)
else
WorkingDirP := nil;
if not CreateProcess(nil, PChar(cmdLine), nil, nil, false, 0, nil,
WorkingDirP, StartupInfo, ProcessInfo) then
begin
Result := false;
ErrorCode := GetLastError;
exit;
end;
with ProcessInfo do
begin
CloseHandle(hThread); // CHECK - CLOSE HERE? or move line down?
if WaitUntilIdle then
WaitForInputIdle(hProcess, INFINITE);
// CHECK ::WaitUntilTerminated was used in C++ sqlcmd.exe
if WaitUntilTerminated then
repeat
Application.ProcessMessages;
until MsgWaitForMultipleObjects(1, hProcess, false, INFINITE, QS_ALLINPUT)
<> WAIT_OBJECT_0 + 1;
CloseHandle(hProcess);
// CHECK :: CloseHandle(hThread); was originally placed here in C++ ...
end;
end;
procedure TestForsqlCmd();
var
errCode: Integer;
success: Boolean;
begin
success := ExecuteProcess('sqlcmd.exe', '-?', '', true, true, true, errCode);
if not success then
begin
s := 'The application ''sqlcmd.exe'' wasn''t found!' + sLineBreak +
'The MS SQLEXPRESS utility is missing.' + sLineBreak +
'Press EXIT when ready.';
MessageDlg(s, TMsgDlgType.mtError, [mbOk], 0);
exit;
end;
end;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Preet Sangha |
Solution 2 | Wai Ha Lee |
Solution 3 | juagicre |