How to get the full computer name in Inno Setup - inno-setup

I would like to know how to get the Full computer name in Inno Setup, for example Win8-CL01.cpx.local in the following image.
I already know how to get the computer name with GetComputerNameString but I also would like to have the Domain name of the computer. How can I get this full computer name or this domain name ?

There's no built-in function for this in Inno Setup. You can use the GetComputerNameEx Windows API function:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
ERROR_MORE_DATA = 234;
type
TComputerNameFormat = (
ComputerNameNetBIOS,
ComputerNameDnsHostname,
ComputerNameDnsDomain,
ComputerNameDnsFullyQualified,
ComputerNamePhysicalNetBIOS,
ComputerNamePhysicalDnsHostname,
ComputerNamePhysicalDnsDomain,
ComputerNamePhysicalDnsFullyQualified,
ComputerNameMax
);
function GetComputerNameEx(NameType: TComputerNameFormat; lpBuffer: string; var nSize: DWORD): BOOL;
external 'GetComputerNameEx{#AW}#kernel32.dll stdcall';
function TryGetComputerName(Format: TComputerNameFormat; out Output: string): Boolean;
var
BufLen: DWORD;
begin
Result := False;
BufLen := 0;
if not Boolean(GetComputerNameEx(Format, '', BufLen)) and (DLLGetLastError = ERROR_MORE_DATA) then
begin
SetLength(Output, BufLen);
Result := GetComputerNameEx(Format, Output, BufLen);
end;
end;
procedure InitializeWizard;
var
Name: string;
begin
if TryGetComputerName(ComputerNameDnsFullyQualified, Name) then
MsgBox(Name, mbInformation, MB_OK);
end;

With built-in functions you can get the full name this way:
[Code]
procedure InitializeWizard;
begin
MsgBox(GetComputerNameString + '.' + GetEnv('UserDnsDomain'), mbInformation, MB_OK);
end;
Although TLama's solution gives you wider possibilities of further development.

Related

Can we make the DwinHs Inno Setup download plugin work faster?

DwinHs has a DwinsHs_Data_Buffer_Length macro. I have set it to a value of 8192 but the download speeds are still rather slow.
For example, I have a 200 MBit connection and the file is 25 MB. It takes two and a half minutes to download.
I have read through some of the answers here:
What is the best memory buffer size to allocate to download a file from Internet?
It suggests a 16K buffer instead. Either way, is there any way we can use a maximum buffer length with Pascal given the user system?
Browsers download faster so why can’t we here in Inno Setup?
Example
[ISPP]
#define HelpDocSetupURL "https://www.publictalksoftware.co.uk/downloads/PublicTalksHelpDocumentationSetup.exe"
[Setup]
AppID = TestID
AppName = Test App
OutputBaseFilename = My_Test_App_Setup
AppVersion = 1.0
DefaultDirName = {pf}\MyTestApp
DefaultGroupName = My Test App
[Tasks]
Name: "downloadhelp"; Description: "Task Desc"; GroupDescription: "Group Desc";
[Files]
Source: "{tmp}\HelpDocSetup.exe"; \
DestDir: "{app}"; \
Flags: external deleteafterinstall; \
Tasks: downloadhelp; \
Check: DwinsHs_Check( ExpandConstant('{tmp}\HelpDocSetup.exe'), '{#HelpDocSetupURL}', 'My_Setup', 'Get', 0, 0 )
[Code]
program Setup;
#define DwinsHs_Use_Predefined_Downloading_WizardPage
#define DwinsHs_Data_Buffer_Length 8192
#include "dwinshs.iss"
procedure InitializeWizard();
begin
DwinsHs_InitializeWizard(wpPreparing);
end;
procedure CurPageChanged(CurPageID: Integer);
begin
DwinsHs_CurPageChanged(CurPageID, nil, nil);
end;
function ShouldSkipPage(CurPageId: Integer): Boolean;
begin
Result := False;
DwinsHs_ShouldSkipPage(CurPageId, Result);
end;
function BackButtonClick(CurPageID: Integer): Boolean;
begin
Result := True;
DwinsHs_BackButtonClick(CurPageID);
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
Result := True;
DwinsHs_NextButtonClick(CurPageID, Result);
end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
DwinsHs_CancelButtonClick(CurPageID, Cancel, Confirm);
end;
The software author got back to me about this issue and proposed:
You can try to set the cache size to 16384, 32768 or 655536.
So I set it to:
#define DwinsHs_Data_Buffer_Length 655536
The results are much better:
As you can see, only 10 seconds.
I don't know what impact such a cache value would have for those who had a slower internet connection.

Determine if Administrator account that runs elevated Inno Setup installer is the same as the account of the current Windows logon session

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.)

Get Image File Information using MediaInfo library in Inno Setup Pascal Script

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.

How to Display blocking message box using inno setup pascal scripting

I'm creating installer for my application using inno setup (pascal script),in my setup there is a requirement that if user runs the setup twice a message has to be displayed saying that "another instance is already running" by checking the mutex, i have impletemented that now the problem is it displays the message box but if user still try's to run the setup again and again the above message willbe displayed multiple times which i don't want.so my message box should block him doing anything on his machine untill the messagebox is closed.
EDIT: I wanted to block the current window from where the user is running the setup, to prevent the user from running the setup from same location again.
my sample code:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
MB_APPLMODAL = $00002000;
MB_SYSTEMMODAL = $00001000;
MB_ICONHAND = $00000010;
MB_ICONQUESTION = $00000020;
MB_ICONEXCLAMATION = $00000030;
MB_ICONASTERISK = $00000040;
MB_ICONSTOP = MB_ICONHAND;
MB_ICONINFORMATION = MB_ICONASTERISK;
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function MessageBox(hWnd: HWND; lpText, lpCaption: string;
uType: UINT): Integer; external 'MessageBox{#AW}#user32.dll stdcall';
function SysModalMsgBox(Owner: HWND; const Text: string; MsgType: TMsgBoxType;
Buttons: Integer): Integer;
var
Flags: UINT;
Caption: string;
begin
Flags := Buttons;
case MsgType of
mbInformation: Flags := Flags or MB_ICONINFORMATION;
mbConfirmation: Flags := Flags or MB_ICONQUESTION;
mbError: Flags := Flags or MB_ICONEXCLAMATION;
mbCriticalError: Flags := Flags or MB_ICONSTOP;
end;
if not IsUninstaller then
Caption := SetupMessage(msgSetupAppTitle)
else
Caption := SetupMessage(msgUninstallAppTitle);
Result := MessageBox(Owner, Text, Caption, MB_SYSTEMMODAL);
end;
procedure InitializeWizard;
begin
Sleep(5000);
SysModalMsgBox(WizardForm.Handle, 'Another instance is runinng please try again!',mbInformation , MB_OK);
end;

Inno Setup check if a machine is joined to a Domain

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;

Resources