There will be used Jenkins automation server.
What I need to do during deployment:
Stop console application
Deploy via MSDeploy service
Run the console application again
The main problem is that the console application has to work always (there is an endless cycle) and it displays important information about processes inside. And admin can logon anytime under Administrator account and see if any error/warning displays in the console window.
What I have for now:
"C:\Program Files\IIS\Microsoft Web Deploy V3\MSDeploy.exe" -verb:sync -preSync:runCommand=D:\Dev\tools\pre-deploy.cmd -postSync:runCommand="powershell -file D:\Dev\tools\run.ps1",waitInterval=3000 -source:contentpath="D:\Publish\" -dest:contentpath="D:\Dev",computername=https://somedomain:8172/MsDeploy.axd,username=adminuser,password=adminpassword,authtype=Basic -allowUntrusted=True -verbose
pre-deploy.cmd just contains script to kill the running process (working well)
run.ps1 constains the next script
$username = 'adminuser';
$password = 'adminpassword';
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword;
$proc = Start-Process D:\Dev\ConsoleApp.exe 0 -Credential $credential -PassThru;
$proc.WaitForExit();
First, D:\Dev\ConsoleApp.exe starts in the background under proper user (it's expected), I can't see the console window and it is not what I'm expecting.
Second, when MsDeploy has been finished deployment it kills powershell process on the remote computer and D:\Dev\ConsoleApp.exe also ends with the parent process.
As for me, the console application should be converted into windows service, then there is no problem with deploying and running it. But the customer wants to see the console window with information inside, and I'm on investigation way now.
It seems there is no way except create a task via Windows Scheduler to run a console application like it was run by user himself.
To run under the specific user you need first off all create some wrapper script
wrapper.ps1
param(
[string] $UserName,
[string] $Password,
[string] $DestPath,
[string] $Engine,
[string] $EngineArgs
)
$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential $UserName, $securePassword;
$proc = Start-Process powershell -ArgumentList "-noexit ""$DestPath\tools\run.ps1"" -UserName $UserName -DestPath """"$DestPath"""" -Engine """"$Engine"""" -EngineArgs $EngineArgs" -Credential $credential -PassThru;
$proc.WaitForExit();
exit 0
then you need create Windows Scheduler task
run.ps1
param(
[string] $UserName,
[string] $DestPath,
[string] $Engine,
[string] $EngineArgs
)
$A = New-ScheduledTaskAction -Execute "$DestPath\$Engine.exe" -Argument $EngineArgs
$T = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(10); $t.EndBoundary = (get-date).AddSeconds(60).ToString('s')
$S = New-ScheduledTaskSettingsSet -StartWhenAvailable -DeleteExpiredTaskAfter 00:00:30
$Task = New-ScheduledTask -Action $A -Trigger $T -Settings $S
$Task | Register-ScheduledTask -Force -TaskName "$Engine For Customer $EngineArgs" -User "$UserName"
#Fix Stuck BITS job
$A = New-ScheduledTaskAction -Execute "powershell.exe" -Argument '-command &{Get-BitsTransfer -AllUsers | Where-Object { $_.JobState -like "TransientError" } | Remove-BitsTransfer}'
$T = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(10); $t.EndBoundary = (get-date).AddSeconds(60).ToString('s')
$S = New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:40
Register-ScheduledTask -Force -user $UserName -TaskName "Fix Stuck BITS" -Action $A -Trigger $T -Settings $S
exit 0
Related
This PowerShell code correctly updates the description attribute of an AD computer:
$comp = Get-ADComputer -Server $server -Filter "Name -eq 'example'" -Properties Description,MemberOf,Location,CanonicalName
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $adUser, (ConvertTo-SecureString $adPass -AsPlainText -Force)
Set-ADComputer $comp -Description "Test" -Credential $creds -Server $server -Confirm:$false
What is the equivalent System.DirectoryServices.Protocols code? My attempt at it produces the error:
System.DirectoryServices.Protocols.DirectoryOperationException: The user has insufficient access rights. 00002098: SecErr: DSID-031514A0, problem 4003 (INSUFF_ACCESS_RIGHTS)
despite successfully authenticating using the same credentials, dc, etc:
var dn = entity.DistinguishedName;
var mod = new ModifyRequest(dn, DirectoryAttributeOperation.Replace, "description", "Test");
//mod.Controls.Add(new PermissiveModifyControl());
conn.SendRequest(mod);
Is this doable using System.DirectoryServices.Protocols or should I switch to some other library?
You can check this code and get the idea of how to do it in Powershell or just use it.
https://www.powershellgallery.com/packages/FreeLDAP/1.0.0.0/Content/Set-LdapUser.ps1
I have the following PowerShell script that 1) installs Azure PowerShell SDK 2) logs in to Azure using the service principle and 3) creates a resource group. I am trying to call this script from C# .NET 6 but I am getting this error:
New-AzResourceGroup -name $recoveryResourceGroupName -location $locat …
| ~~~~~~~~~~~~~~~~~~~
| The term 'New-AzResourceGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I think it's not running the PowerShell script code at all.
Note that the actual script does a lot more than just creating a resource group, but this is just an example.
// The difference between CreateDefault and CreateDefault2 is that
// CreateDefault includes engine snap-ins, while CreateDefault2 does not.
var initialState = InitialSessionState.CreateDefault2();
using var ps = PowerShell.Create(initialState);
var results = await ps.AddScript(#"
[string][ValidateNotNullOrEmpty()] $applicationId = """"
[string][ValidateNotNullOrEmpty()] $secret = """"
[string][ValidateNotNullOrEmpty()] $subscriptionId = """"
[string][ValidateNotNullOrEmpty()] $tenantId = """"
# Install Azure Powershell modules
Write-Output "Installing Modules..."
if (Get-Module -ListAvailable -Name 'Az*') {
Write-Output " Az Already Installed"
}
else {
Install-Module -Name 'Az' -Scope CurrentUser -Repository PSGallery -Force
Write-Output "Installed AZ"
}
# Import Azure module
Import-Module 'Az'
# Login to azure using credentials from the KeyVault
$secretAsSecureString = ConvertTo-SecureString -String $secret -AsPlainText -Force
$pscredential = New-Object -TypeName System.Management.Automation.PSCredential($applicationId, $secretAsSecureString)
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId
# Select Right subscription
Set-AzContext $subscriptionId
New-AzResourceGroup -Name 'TestRg123' -Location 'eastus2euap'
").InvokeAsync();
foreach (PSObject outputItem in results)
{
Debug.WriteLine(outputItem);
}
UPDATE #1:
I updated the script and added -AllowClubber to make Az is installed but this is what I am getting in the output:
I think Az is not getting installed and for some reason it think Az is already installed
And then
New-AzResourceGroup:
Line |
97 | New-AzResourceGroup -name $recoveryResourceGroupName -location $locat …
| ~~~~~~~~~~~~~~~~~~~
| The term 'New-AzResourceGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
UPDATE #2: I modified the PowerShell script to unconditionally install the Az and I am still getting the same error that New-AzResourceGroup is not defined
Check your powershell version and try to download latest:
https://github.com/PowerShell/PowerShell
In your script you should be able to use:
Import-Module Az.Resources
#Just in case
Az Upgrade
I have got similar error when i am using command
New-AzResourceGroup
Then i have used Azure cli commands then i get the resource group created in azure
My powershell script(Updated your script):
using System.Diagnostics;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
var initialState = InitialSessionState.CreateDefault2();
initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
using var ps = PowerShell.Create(initialState);
var results = ps.AddScript(#"
Install-PackageProvider -Name Nuget -Scope CurrentUser –Force
Install-Module –Name PowerShellGet -Scope CurrentUser –Force
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
Install-Module -Name Az.Resources -AllowClobber -Scope CurrentUser
# Import Azure module
Import-Module 'Az'
Import-Module 'Az.Accounts'
Import-Module 'Az.RecoveryServices'
az login
try {
az account set --subscription ""XXX"
az group create --name rithDemo --location eastus
}
catch
{
$string_err = $_ | Out-String
Write-Output ""Failed to run test $testname because $string_err""
}
").Invoke();
XXX- Subscription name
rithDemo- resource group name
In script I have first login into azure using az login. Then you will be redirected to azure login page there you can login.
Then I set the subscription using az account set command
Then I created a resource group using az group create
Also added AllowClobber in script
By this process the resource group got created.
Output:
I'm trying to create a powershell script that start process with system user account. And I want to use a registered application in AAD as that system user account.
Here the code that I create.
$ApplicationId = "My ApplicationID"
$ServicePrincipalSecret = "My Application's secret Key"
$SecurePassword = ConvertTo-SecureString –String $ServicePrincipalSecret –AsPlainText -Force
$Credential = New-Object System.Management.Automation.PsCredential ($ApplicationId, $SecurePassword)
Start-Process -FilePath notepad -Credential $Credential
this code dose not work. and return following error massage.
Start-Process : This command cannot be run due to the error: The user
name or password is incorrect. At line:1 char:1
+ Start-Process -FilePath notepad -Credential $Credential
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
I tried following command to check my $Credential is correct, and successfully connected Azure. So my Credential object is created properly.
Connect-AzureRmAccount -Credential $Credential -Tenant "My Azure tenant ID" -ServicePrincipal
I also tried following code.
$psinfo = New-Object System.Diagnostics.ProcessStartInfo
$psinfo.FileName = "notepad"
$psinfo.UserName = $ApplicationId
$psinfo.Password = $SecurePassword
$psinfo.Verb = "runasuser"
$psinfo.UseShellExecute = 0
$psinfo.LoadUserProfile = 0
$ps = New-Object System.Diagnostics.Process
$ps.StartInfo = $psinfo
$ps.Start()
this code dose not work either. and return following error massage.
Exception calling "Start" with "0" argument(s): "The stub received bad
data" At line:1 char:1
+ $ps.Start()
+ ~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Is there any good way to kick process with a user account that is qualified to manage Azure Active Directory different from a user who actually run the script? if anyone give me any advice will be appreciated.
thanks.
Try something like below.It worked for me.
$uid = "Domain\username"
$pwd = "#pwd"
$Args = "-Verb RunAs -Wait -passthru"
$MyCredential=New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $Uid, ($pwd | ConvertTo-SecureString -AsPlainText -Force)
Start-Process -FilePath C:\windows\system32\system32\notepad.exe -Credential ($cred) -Argumentlist $Args
this is for when you want to prompt for credential, else you can simple use below command
$MyCredential=New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $Uid, ($pwd | ConvertTo-SecureString -AsPlainText -Force)
Start-Process -FilePath C:\windows\system32\system32\notepad.exe -Credential -Credential Get-Credential -Argumentlist $Args
Please check this and see if it works for you, else will take a look further with you.
I found out that my problem was because of authentication with non-exist user.
Registered Application in Azure Active Directory wont be synced to Azure Active Directory Domain Service. So even if I tried to perform change/update to AADDS with AAD application service principal credential, authentication failed.
Using AAD User object instead of service principal worked for me.
thanks.
So I try to invoke a PS script from a ASPX/C# application. When I run the PS script from commandline (PS C:\scripts> ./do-barrelRoll.ps1 -s remoteComputer) it works as expected. But when I use C# it cannot connect to the remote computer (wrong user/password). Fun fact: The user and password to use are inside a config section in the PS script itself (see $SETUP variable)! What am I doing wrong?
Exact error message from ASPX (the server name is correct!):
[remoteComputer] Connecting to remote server remoteComputer failed with the following error message : The user name or password is incorrect
Relevant parts of the PS Script:
set-alias new New-Object
$passwd = $SETUP["password"] | ConvertTo-SecureString -asplaintext -force
$session = new -TypeName System.Management.Automation.PSCredential -argumentlist $SETUP["user"], $passwd
Invoke-Command –ComputerName $PARAM["s"] -Credential $session –ScriptBlock {
# Do a barrel roll
}
Relevant parts of ASPX/C# application:
using System.Management.Automation;
public ActionResult doAction(string server, string action)
{
var split = server.Split(';');
//...
var ps = PowerShell.Create();
ps.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -f; C:\\scripts\\do-barrelRoll.ps1 -s " + split[1]);
Collection<PSObject> results = ps.Invoke();
// Here I retrive the results and the content of the error stream and display them
}
It works as expected at the command line most likely because your account has full script access and can run everything. The account that .NET runs under should be more constrained. You'll have to check that the account has rights to run unrestricted scripts. Check local policies and then go up from there. You most likely are not the same account that the .NET application is running as.
I have powershell script to fetch exchange users and this script gets called from C#. This also creates temp files in temp directory. But when called from c# the Get-PSSession|Remove-PSSession is not deleting temp files. But it removes temp files when the script is executed from Powershell window.
Function GetExchangeUsers($userName, $cred){
try{
$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $ExSession -AllowClobber | Out-Null
$exchangeUsers=Get-MailBox -Filter '(RecipientTypeDetails -eq "UserMailBox")' | select UserPrincipalName,InPlaceHolds
return $exchangeUsers
}
finally{
get-module | Remove-Module
Get-PSSession|Out-File "F:\FinallyGetExchangeUsers.txt"
Get-PSSession|Remove-PSSession
Get-PSSession|Out-File "F:\AfterFinallyGetExchangeUsers.txt"
}
}
What can be the issue here?