Am trying to find out how can I check, if proxy is being used in the computer via Inno Setup.
You can use the WinHttpGetDefaultProxyConfiguration function:
type
WINHTTP_PROXY_INFO = record
AccessType: Cardinal;
Proxy: Cardinal;
ProxyBypass: Cardinal;
end;
function WinHttpGetDefaultProxyConfiguration(var ProxyInfo: WINHTTP_PROXY_INFO): Boolean;
external 'WinHttpGetDefaultProxyConfiguration#winhttp.dll stdcall';
function StrCpyN(S1: string; S2: Cardinal; Max: Cardinal): Cardinal;
external 'StrCpyNW#shlwapi.dll stdcall';
function GetProxy: string;
var
ProxyInfo: WINHTTP_PROXY_INFO;
begin
if WinHttpGetDefaultProxyConfiguration(ProxyInfo) then
begin
SetLength(Result, 1024);
StrCpyN(Result, ProxyInfo.Proxy, Length(Result) - 1);
Result := Trim(Result);
Log('Retrieved proxy information: ' + Result);
end
else
begin
Log('Cannot retrieve proxy information');
end;
end;
Requires Unicode Inno Setup (the only version as of Inno Setup 6).
You can also use netsh winhttp show proxy command.
Related
Code was working normally, but after upgrading to inno 6.0.2, i got an error when compile. Error:
Type mismatch
in line if LoadStringFromFile(TmpFile, ExecStdout) then code as below:
function NextButtonClick(CurPageID: Integer): Boolean;
var
TmpFile, ExecStdout: string;
ResultCode: integer;
begin
Result := True;
if CurPageID = HostingPage.ID then
begin
Domain := HostingPage.values[0];
DomainPort := HostingPage.values[1];
TmpFile := ExpandConstant('{tmp}') + '\~pid.txt';
Exec('cmd.exe',
'/C FOR /F "usebackq tokens=5 delims= " %i IN (`netstat -ano ^|find "0.0:'+DomainPort+'"`) DO '
+ '#tasklist /fi "pid eq %i" | find "%i" > "' + TmpFile + '"', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode);
if LoadStringFromFile(TmpFile, ExecStdout) then
begin
MsgBox('The Port ('+DomainPort+') ' #13 + ExecStdout, mbError, MB_OK);
Result := False;
end;
DeleteFile(TmpFile);
end;
end;
The code you posted in not complete, always post MCVE.
The problem resides in using wrong type of parameter, see the documentation:
function LoadStringFromFile(const FileName: String; var S:
AnsiString): Boolean;
Change it like this:
function NextButtonClick(CurPageID: Integer): Boolean;
var
TmpFile: String;
ExecStdout: AnsiString; // << Was String in your script
ResultCode: Integer;
This is because Inno Setup 6 is Unicode only:
Change in default behavior: Starting with Inno Setup 6 there's only one version available: Unicode Inno Setup. Unicode Inno Setup has been available for 9 years but in case you have not yet updated to it: please see the Unicode Inno Setup topic in the help file for more information. Basically, unless you're using [Code] to make DLL calls with string parameters you shouldn't have to make any changes to your script.
I am using PrivilegesRequired=lowest in my Inno Setup script. If setup is running elevated, i.e. IsAdminLoggedOn or IsPowerUserLoggedOn reports TRUE, how can I determine if the elevated user account is the same account from which setup was launched?
My script can do different things accordingly.
You can use WTSQuerySessionInformation to retrieve an account username for the current Windows logon session.
function WTSQuerySessionInformation(
hServer: THandle; SessionId: Cardinal; WTSInfoClass: Integer;
var pBuffer: DWord; var BytesReturned: DWord): Boolean;
external 'WTSQuerySessionInformationW#wtsapi32.dll stdcall';
procedure WTSFreeMemory(pMemory: DWord);
external 'WTSFreeMemory#wtsapi32.dll stdcall';
procedure RtlMoveMemoryAsString(Dest: string; Source: DWord; Len: Integer);
external 'RtlMoveMemory#kernel32.dll stdcall';
const
WTS_CURRENT_SERVER_HANDLE = 0;
WTS_CURRENT_SESSION = -1;
WTSUserName = 5;
function GetCurrentSessionUserName: string;
var
Buffer: DWord;
BytesReturned: DWord;
QueryResult: Boolean;
begin
QueryResult :=
WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSUserName, Buffer,
BytesReturned);
if not QueryResult then
begin
Log('Failed to retrieve username');
Result := '';
end
else
begin
SetLength(Result, (BytesReturned div 2) - 1);
RtlMoveMemoryAsString(Result, Buffer, BytesReturned);
WTSFreeMemory(Buffer);
Log(Format('Retrieved username "%s"', [Result]));
end;
end;
(The code is for Unicode version of Inno Setup – The only version as of Inno Setup 6).
You can then compare the result against GetUserNameString.
You may need to add a domain name into the comparison.
If you need the full account name of the current user (e.g., authority\username format), you can use the GetUserNameExW Windows API function. The below snippet demonstrates how to call this function from Inno Setup:
const
ERROR_MORE_DATA = 234;
function GetUserNameExW(NameFormat: Integer; lpNameBuffer: string; var nSize: DWORD): Boolean;
external 'GetUserNameExW#secur32.dll stdcall';
function GetFullUserName(): string;
var
NumChars: DWORD;
OutStr: string;
begin
result := '';
NumChars := 0;
if (not GetUserNameExW(2, '', NumChars)) and (DLLGetLastError() = ERROR_MORE_DATA) then
begin
SetLength(OutStr, NumChars);
if GetUserNameExW(2, OutStr, NumChars) then
result := Copy(OutStr, 1, NumChars);
end;
end;
(The value 2 passed to the first parameter (NameFormat) in the GetUserNameExW function corresponds to NameSamCompatible in the EXTENDED_NAME_FORMAT enumeration.)
I have been trying for more than two days to get JPEG Image and MP4 Video File Information using MediaInfo.DLL in my Pascal Script.
But I keep getting error
Runtime Error (at 6:366) - Access Violation at address 0042FD23. Read of address 8065241E.'
The error mostly points to (at 6:366).
I can't think what problem is causing this exception when trying to get Media Information using MediaInfo.DLL.
The code I added to my Script:
[Files]
Source: Lamborghini_Aventador.jpg; DestDir: {tmp}; Flags: dontcopy
Source: MediaInfo.dll; DestDir: {tmp}; Flags: dontcopy
[Code]
#ifdef UNICODE
type
PWideChar = WideString;
#endif
const
StreamKind_Image = 5;
InfoKind_Text = 1;
function MediaInfo_New: Cardinal;
external 'MediaInfo_New#{tmp}\MediaInfo.dll stdcall delayload';
function MediaInfo_Open(Handle: Cardinal; File__: PWideChar): Boolean;
external 'MediaInfo_Open#{tmp}\MediaInfo.dll stdcall delayload';
function MediaInfo_Get(Handle: Cardinal; StreamKind: Integer; StreamNumber: Integer; Parameter: PWideChar; KindOfInfo: Integer; KindOfSearch: Integer): PWideChar;
external 'MediaInfo_Get#{tmp}\MediaInfo.dll stdcall delayload';
procedure RetrieveImageInformation;
var
IHandle: Cardinal;
Width: PWideChar;
begin
ExtractTemporaryFile('Lamborghini_Aventador.jpg');
ExtractTemporaryFile('MediaInfo.dll');
IHandle := MediaInfo_New();
MediaInfo_Open(IHandle, PWideChar(ExpandConstant('{tmp}\Lamborghini_Aventador.jpg')));
Width := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, 0);
Log('Width of the JPEG Image: ' + PWideChar(Width) + '.');
end;
The line which the exception is generating is:
Width := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, 0);
I expected that the compiler output will be Width of the JPEG Image: 1920.
I use latest version of Unicode Inno Setup Compiler (5.5.9 - U)
Thanks in advance for your important help.
I do not think you can call a function that returns a pointer to a string (character buffer) from Inno Setup Pascal Script.
But you can hack it like this:
Declare the function as if it returns Cardinal;
Use some available function that takes a pointer and copies it to another pointer. Declare the source pointer as Cardinal and the target pointer as string. One such function is the StrCpyN.
function MediaInfo_Get(
Handle: Cardinal; StreamKind: Integer; StreamNumber: Integer;
Parameter: string; KindOfInfo: Integer; KindOfSearch: Integer): Cardinal;
external 'MediaInfo_Get#{tmp}\MediaInfo.dll stdcall delayload';
function StrCpyN(S1: string; S2: Cardinal; Max: Cardinal): Cardinal;
external 'StrCpyNW#shlwapi.dll stdcall';
var
P: Cardinal;
S: string;
begin
P := MediaInfo_Get(IHandle, StreamKind_Image, 0, 'Width', InfoKind_Text, InfoKind_Name);
S := StringOfChar(' ', 1024);
StrCpyN(S, P, Length(S) - 1);
S := Trim(S);
...
end;
The code requires Unicode Inno Setup (the only version as of Inno Setpu 6).
You can use the MediaInfo Command Line Interface with Inno Setup Ansi or Unicode Version.
Usage Example:
[Files]
Source: MediaInfo.exe; DestDir: {tmp}; Flags: Dontcopy
[code]
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
begin
ExtractTemporaryFile('MediaInfo.exe');
ShellExec('Open', 'MediaInfo.exe', ExpandConstant('"YourFileName.mp4" --LogFile="YourFileName Prperties.log"'), ExpandConstant('{tmp}'), SW_HIDE, ewWaitUntilTerminated, ErrorCode);
if SysErrorMessage(DLLGetLastError) = SysErrorMessage(0) then
Result := True;
end;
Now, navigate to the Inno Setup Temporary Directory as Administrator using Run (Windows Key + R) Command and see your Media Information Log File exists there which contains the Information about the File you given in the Command.
Is there a way of checking whether the machine you are installing on is joined to a Domain or in a Workgroup?
I found this article about how to do this in Delphi, but I am unable to get this working within Inno Setup. Can anyone assist with this? Is this even possible?
http://delphi.about.com/od/delphitips2009/qt/computer-in-a-domain.htm
I would translate (and shorten) it this way:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
NERR_BASE = 2100;
NERR_SetupNotJoined = NERR_BASE + 592;
type
NET_API_STATUS = DWORD;
function NetRenameMachineInDomain(lpServer: WideString;
lpNewMachineName: WideString; lpAccount: WideString;
lpPassword: WideString; fRenameOptions: DWORD): NET_API_STATUS;
external 'NetRenameMachineInDomain#netapi32.dll stdcall';
function IsInDomain: Boolean;
begin
Result := NetRenameMachineInDomain('', '', '', '', 0) <> NERR_SetupNotJoined;
end;
procedure InitializeWizard;
begin
if IsInDomain then
MsgBox('Is in domain.', mbInformation, MB_OK)
else
MsgBox('Is not in domain.', mbInformation, MB_OK);
end;
I tried to add mp3 audio playback (LAME encoded) to my Inno setup program using Inno Media Player and following #TLama's decription -> https://stackoverflow.com/a/12360780/3838926. I use Windows 7 64bit with Unicode Inno.
Unfortunately it fails: When opening the installer I get the following error message: TDirectShowPlayer error: -2147220890; Searching through Google didn't help.
What do I do wrong? Is it a bug in the program? I'm clueless...
Here's the exact code:
const
EC_COMPLETE = $01;
type
TDirectShowEventProc = procedure(EventCode, Param1, Param2: Integer);
function DSGetLastError(var ErrorText: WideString): HRESULT;
external 'DSGetLastError#files:mediaplayer.dll stdcall';
function DSPlayMediaFile: Boolean;
external 'DSPlayMediaFile#files:mediaplayer.dll stdcall';
function DSStopMediaPlay: Boolean;
external 'DSStopMediaPlay#files:mediaplayer.dll stdcall';
function DSSetVolume(Value: LongInt): Boolean;
external 'DSSetVolume#files:mediaplayer.dll stdcall';
function DSInitializeAudioFile(FileName: WideString;
CallbackProc: TDirectShowEventProc): Boolean;
external 'DSInitializeAudioFile#files:mediaplayer.dll stdcall';
procedure OnMediaPlayerEvent(EventCode, Param1, Param2: Integer);
begin
if EventCode = EC_COMPLETE then
begin
// playback is done, so you can e.g. play the stream again, play another
// one using the same code as in InitializeWizard (in that case would be
// better to wrap that in some helper function) or do just nothing
end;
end;
procedure InitializeWizard;
var
ErrorCode: HRESULT;
ErrorText: WideString;
begin
ExtractTemporaryFile('InDeep.mp3');
if DSInitializeAudioFile(ExpandConstant('{tmp}\InDeep.mp3'),
#OnMediaPlayerEvent) then
begin
DSSetVolume(-2500);
DSPlayMediaFile;
end
else
begin
ErrorCode := DSGetLastError(ErrorText);
MsgBox('TDirectShowPlayer error: ' + IntToStr(ErrorCode) + '; ' +
ErrorText, mbError, MB_OK);
end;
end;
procedure DeinitializeSetup;
begin
DSStopMediaPlay;
end;
InDeep.mp3 is my audio file.
Thanks in advance!!