2
votes

I am setting up powershell scripts to automate environment installs for a variety of systems. I need to script the running of an MSI installer file to setup a Windows Service. How do I include the required Username and Password to make the installation fully 'quiet'

I've gotten to:

$installFile = "C:\[path]\Installer.msi"
$username = "[ad user account]"
$password = convertto-securestring -String "[secure password]" -AsPlainText -Force  

msiexec /i $installFile /quiet "UserName=$username,Password=$password"

but the provided credentials are not being accepted.

Suggestions?

2
First run it with hard coded values to prove it can work. Only then try it with variables. Then copy the complete script into the question with the exact error message.John Rees
The MSI and the Windows Service that it installs are both fine; I ironed those issues out months ago. The script above doesn't throw an error, but it does prompt for the service credentials to be entered. I'm trying to provide the credentials up front so the install is fully automated.user11861660
Great. Now please show the complete script and error message.John Rees
If you want a unattended installation you've to add the /quiet switch.Moerwald
Yes, the /quiet switch after the $installFile does supress the normal windows, it still pops up the window for the credentials the service is to run under. That is the issue I need help resolving.user11861660

2 Answers

2
votes

First of all, thank you everyone for your help.

Reading through your suggestions and the following question in the list of “Related” suggestions got me thinking in another direction (Msi insaller passing paramenter from command prompt for Set Service Login).

A little more hunting and I found this article: Change Service Account Username & Password–PowerShell Script

So, my new plan is to default the service account inside installer via code and then change it after installation using PowerShell. In the source code for the windows service I have a ProjectInstaller.cs file. Opening the ProjectInstaller.Designer.cs code and looking in the InitializeComponent() method I saw the following lines:

this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;

Adding the following line below successfully suppresses any request for service account credentials during installation:

this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;

After that I used the code sample from the TechNet article to change the account post-installation. The final script looks something like this:

$serviceName = "Service"
$oldInstallFile = "C:\Old_Installer.msi" #Only required if upgrading a previous installation
$installFile = "C:\New_Installer.msi"

$serviceConfigSource = "C:\Config"
$serviceConfigSourceFile = "C:\Config\Service.exe.config"
$serviceConfigDestinationFile = "C:\Program Files (x86)\Service\Service.exe.config"

$username = "[UserName]"
$password = "[Password]"  


#Checking for existing service installation and uninstalling it
$existingService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"

if($existingService)
{
    Write-Host "$serviceName found. Begining the uninstall process..."
    if($existingService.Started)
    {
        $existingService.StopService()
        Start-Sleep -Seconds 5
    }

    msiexec /uninstall $oldInstallFile /quiet
    Start-Sleep -Seconds 5
    Write-Host "$serviceName Uninstalled."

}

#Install New service
Write-Host "$serviceName installation starting."
msiexec /i $newInstallFile /quiet
Start-Sleep -Seconds 5
Write-Host "$serviceName installation completed."



#copy config file
if(Test-Path $serviceConfigSource)
{
    Copy-Item -Path $serviceConfigSourceFile -Destination $serviceConfigDestinationFile -Force
}


#Final service setup and start up
$newService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"

$changeStatus = $newService.Change($null,$null,$null,$null,$null,$null,$userName,$password,$null,$null,$null) 
if ($changeStatus.ReturnValue -eq "0")  
{
    Write-Host "$serviceName -> Sucessfully Changed User Name"
} 

if(!$newService.Started)
{
    $startStatus = $newService.StartService()
    if ($startStatus.ReturnValue -eq "0")  
    {
        Write-Host "$serviceName -> Service Started Successfully"
    } 

}

Hope this helps people.

0
votes

Try to seperate your arguments with spaces:

 $installArgs = "UserName=$username Password=$password" 

Afterwards you can call msiexec via:

 $msiArgs = "/i ""{0}"" /qn /norestart /l*v ""C:\temp\msiInstall.log"" {1}" -f $msiLocation,$installArgs
 $process = Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru
 if ($process.ExitCode -ne 0) {
      Write-Error "Installation failed"
 }