I cannot redirect or hide Get-VM output - powershell

So I have a line of code to retrieve the VMID from a hyper-v vm. Running on Server 2016 so it should be at least Powershell 5.0.
[string]$vmid = (Get-VM $VMName).VMID
Pulls out the ID just how I need. The problem is the script also prints out the full result of Get-VM. I cannot for the life of me figure out how to mute or redirect it.
[void] doesn't work cause I'm pulling it into a string.
*> $null, 2> $null, 1> $null all do nothing, and I've tried both in the parenthesis and after the expression.
Piping to Out-Null has no effect either in those locations.
Any idea how I'm supposed to hide this? I really don't need all this info.

On my hyper-v server I had to run
$vmid = (Get-VM $VMName).VMid.Guid
to save only the string to variable
The above command works for me, so it's probably somewhere else in your code that you are getting the unwanted output?

So instead of the above, I ended up defining a $vm variable when creating the VM, then using it in the operations below.
$vm = New-VM ...
...
[string]$vmid = $vm.VMID.GUID

Related

Running a command with arguments assistance

I have a command which runs a program in silent mode, it uses an XML file for the data repository and a word template to create multiple word documents based on a filter xml file.
The command I use is:
"P:\ath to\executable" -Username:Admin -Password:Pa55w0rd -Datadefinition:"C:\Data.xml" -Datafilter:"C:\Filter.xml" -wordtemplate:"C:\Batch\Paul1.dotx" -Targetdocument:="C:\Batch\Paul1.pdf" -filetype:PDF -Log:"C:\Logs\error.log" -Usage:DOCGENSILENT
I need to run this as a PowerShell script which I have mostly managed:
set-executionpolicy unrestricted
$datadefinition = Get-Content "C:\Data file.xml"
$datafilter = Get-Content "C:\Filter for data file.xml"
$wordTemplate = Get-Content "C:\"C:\Template\Paul1.dotx"
$targetFolder = Get-Content "C:\"C:\Paul\Paul.pdf"
Stop-Job = "Executable path" -Username:Admin -Password:Pa55w0rd -Datadefinition:%dataDefinition% -Datafilter:%dataFilter% -wordtemplate:%wordTemplate% -Targetdocument:%targetFolder% -filetype:docx -Log:%logPath% -Usage:DOCGENSILENT
Stop-Job 1
set-executionpolicy restricted
Write-Host -NoNewLine "Press any key to continue..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
My issue is that the script starts the executable but then doesnt pass the Variables, can anyone guide me in the right direction to fix this?
Getting this working depends on the behavior of your executable. Some things I noticed:
Shouldn't this:
$wordTemplate = Get-Content "C:\"C:\Template\Paul1.dotx"
be this:
$wordTemplate = "C:\Template\Paul1.dotx"
Are you sure you need Get-Content? (Aside from that, the path and quoting in your sample are not correct.)
Shouldn't this:
$targetFolder = Get-Content "C:\"C:\Paul\Paul.pdf"
be this:
$targetDocument = "C:\Paul\Paul.pdf"
I doubt Get-Content is correct here, since presumably your output file doesn't exist yet? I also renamed the variable so it makes more sense in your command.
In fact, are you sure you need Get-Content for any of those? Aren't you specifying filenames, not the content of the files?
In PowerShell, variables are prefixed with $ rather than being surrounded by %.
Using Set-ExecutionPolicy within a script to enable scripts to run is pointless, because the script is already running. (That is, if execution policy prevented script execution, PowerShell wouldn't let you run the script in the first place.)
If my guesses regarding your variables are correct, I think your script should look something like this (note also that I specified a $logFile variable, which I didn't see in your script):
$datadefinition = "C:\Users\Administrator\data\Sample Model_146_object type(s).xml"
$datafilter = "C:\Users\Administrator\data\Sample Model_146_object type(s).xml"
$wordtemplate = "C:\Users\Administrator\Templates\Base object.docx"
$targetdocument = "C:\Users\Administrator\Result\sample test15"
$logfile = "C:\Users\Administrator\Logs\C4W Error.log"
& "C:\Program Files (x86)\Communicator4Word.exe" -Username:Admin -Password: -Datadefinition:$datadefinition -Datafilter:$datafilter -wordtemplate:$wordtemplate -Targetdocument:$targetdocument -filetype:docx -Log:$logfile -Usage:DOCGENSILENT
I don't know the behavior of Communicator4Word.exe when you use -Password: with no password after it. (Is that a syntax error, or should you just omit -Password: altogether?)

Invoke-AzureRmVMRunCommand not returning anything in "Output" field when executing from Runbook

I'm trying to invoke a powershell script on to a Virtual Machine and retrieve the output of the script. I'm using the Invoke-AzureRmVMRunCommand cmdlet to invoke the script on the VM as shown below.
$ValidationResult = Invoke-AzureRmVMRunCommand -ResourceGroupName $VM.ResourceGroupName -VMName $VM.Name -CommandId "RunPowerShellScript" -ScriptPath $ValidationScript
When I execute the above cmdlet from a regular powershell terminal, I get the output as expected. However, whenever I'm putting this statement inside an automation runbook, I get null in almost all the fields as shown below
I don't see anything specific to this in documentation as well. Am I doing something wrong here?
Any help would be greatly appreciated! Thank you.
Update:
In the script, I'm logging the output using Write-Output cmdlet.
You need to either add the object name on last line of your script or use the Write-Output command. Otherwise it will not output anything.
The following lines both write an object to the output stream.
Write-Output –InputObject $ValidationResult
$ValidationResult
https://learn.microsoft.com/en-us/azure/automation/automation-runbook-output-and-messages
Hope this helps
This issue is most likely due to a reported bug in the AzureRM modules starting with version 5.7.0 / April 2018. Rolling back to version 5.6.0 / March 2018 is reported to fix it. Issue log: https://github.com/Azure/azure-powershell/issues/5982
My Apologies for the delayed response. I was using this in a runbook of type Powershell Workflow. Many of the PowerShell cmdlets behave differently when executed in workflows.
So in this case, what was happening is the Invoke-AzureRmVMRunCommand was executing correctly but the response was only the TYPE of the response and not the actual response object. Hence I was unable to see any values in the response's properties.
In order to make this work, I had to wrap the cmdlet call within an InlineScript {} block.
$ValidationResult = InlineScript {
$result = Invoke-AzureRmVMRunCommand -ResourceGroupName $USING:VM.ResourceGroupName -VMName $USING:VM.Name -CommandId "RunPowerShellScript" -ScriptPath $USING:ValidationScript
$result.SubStatuses[0].Message
}
The result is returned to $ValidationResult variable.
More detailed post is given here: https://amoghnatu.net/2018/04/15/get-output-of-script-executed-as-part-of-set-azurermvmcustomscriptexecution-cmdlet/
Thanks.

$env:homedrive is lost occasionally

I use $env:homedrive in my scripts in Azure's CustomScriptExtension.
Strangely sometimes I got blank from this variable but sometimes OK.
Is this environment variable not reliable?
It's difficult to say without looking at the script. But you can put a $null condition check before proceeding.
if($env:HOMEDRIVE -eq $null){
$env:HOMEDRIVE = "H:" # Whatever you want
}
else{
Do-WhatYouWant
}
Alternative you can set $env:HOMEDRIVE directly to your desired location at the beginning of the script or function. But still, I would prefer to put the $null check condition always.
#Dave Wu
If it concerns a script at logon, it is possible that network is not loaded yet due to windows fast logon. Maybe directly pulling it from the registry is more reliable:
(Get-Item -ErrorAction SilentlyContinue "HKCU:\Volatile Environment").GetValue("HomeDrive")

Powershell is reanimating variables in Scripts

Good evening
I have this Problem with this Version
PS C:\temp> $PSVersionTable.PSVersion.Major
4
This is a really strange problem...
despite of initialized variables, PowerShell script is somehow able to reuse variable values from previous invocations.
The script is simple; to show the problem, I work with a list of virtual machines:
Read all Virtual Machines into an Array
Select the 1st Element in the Array
Add a new Property to the Object from step 2
The Problem: if I run the script a second time, the new Property is already there - despite all Variables are initialized. If I start the Script in a new session, the new Property is missing on the 1st run, afterwards it is already there.
Here is the simple Code:
Set-StrictMode -Version 2.0
# Read all Virtual Machines into an Array
$AllVMs = #()
$AllVMs = Get-VM
# Get the 1st Virtual Machine
$VM = $null
$VM = $AllVMs[0]
# Prepare my Property
$MyList = #()
$MyList += "Test"
# If the Property already exists, just add my List
if ($VM.PSobject.Properties.Name -match "MyList") {
$VM.MyList += $MyList
} else {
# My Property does not exist: create it
$VM | Add-Member –MemberType NoteProperty –Name MyList –Value ($MyList)
}
# Give Back my VM Object
$VM
To test the script, I just count the number of MyList-Elements:
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
1
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
2
…
Does somone can help me with this Problem?
Thanks a lot for any help!!
Kind regards,
Tom
I have asked this question to 'the scripting guy' Forum, too.
I've got two great answers:
From jrv:
You are not exiting from PowerShell. The VM object is dynamic to the session. It persists until you close PowerShell. Some objects are like this. The code base drags them I to PowerShell and they remain cached. I suspect this is what is happening here.
From Evgenij Smirnov:
Hi,
this appears to be specific to the VM object. If I substitute Get-VM by Get-Process or Get-ChildItem c:\ I do not experience this behaviour. If I select a new VM every time I run the script, it does not retain the property. On the other hand, if I do (Get-VM)[0].MyList after running the script four times, I get four entries.
So this persistence is obviously built into the Hyper-V module, the custom property getting added to the instance of the VM object itself. So you could initialize MyTest to empty on the whole VM collection like this:
$AllVMs | foreach {
if ($_.PSobject.Properties.Name -match "MyList") {
$_.MyList = #()
}
}
Kind regards, Tom

Return code and status from PowerShell command

I'm running the following command from within a Microsoft System Centre Orchestrator PowerShell activity:
Install-WindowsFeature -ConfigurationFilePath C:\DeploymentConfigTemplate.xml -ComputerName ServerXYZ
the command isn't doing what it's supposed to do, and I want to be able to return if the command was successful or not, and any error message if possible. Ignore the fact it's running in Orchestrator, as I'm more concerned about the PowerShell question. When I run the command from ISE it does what it's supposed to do, that's why I want to see what is returned from PowerShell.
Thanks.
It's hard to know what may be happening without more context. The following will record any errors encountered in an xml file that you can import later with import-clixml:
Install-WindowsFeature -ConfigurationFilePath C:\DeploymentConfigTemplate.xml -ComputerName ServerXYZ
IF (!($?)) {
$error[0] | export-clixml C:\myerror.xml
}
This solves my problem:
$Result = Install-WindowsFeature -Name SNMP-Service -IncludeAllSubFeature -IncludeManagementTools
Write-Host $Result.ExitCode