Posts mit dem Label Powershell werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Powershell werden angezeigt. Alle Posts anzeigen

Donnerstag, 27. Juni 2013

PowerShell: export XML content to text file (SCCM Configuration Item)

Hi,
this is one of my favourites scripts i did for SCCM, to manage Desired Configuration Management in a better way, and it was lost for a long time. It helps you to get settings extracted out of an SCCM configurtation item XML-File. Maybe you got some ".cab" files and want to know what settings are in there without using a tool which cannot export those data to a text file or an excel sheet.
What this script does is very simple, it reads the content of an xml file and creates an XML objects which can be used in powershell.

$path = "D:\xml-output.txt" #the text file you want to create
"New file" > $path
$myxml = [XML](get-content "D:\xml-file.xml")
$settings = $myxml.DesiredConfigurationDigest.BusinessPolicy.settings.rootcomplexsetting.ComplexSetting | foreach-object {$_.simplesetting}
"#############################################################################"  >> $path
" All Settings"  >> $path
"#############################################################################"  >> $path
$settings | %{$_.Rules.Rule} | select LogicalName,Operation,OperandA | ft -Property * -AutoSize | Out-String -Width 4000 >> $path
"#############################################################################"  >> $path
"Registry Values"  >> $path
$settings | %{$_.RegistryDiscoverySource} | ft -Property * -AutoSize | Out-String -Width 4000 >> $path
"#############################################################################"  >> $path
"WMI Entries"  >> $path
$settings | %{$_.WqlQueryDiscoverySource} | ft -Property * -AutoSize | Out-String -Width 4000   >> $path
This one is a very specific script for SCCM, but you can edit it and change it to your needs.

Customizing the output that it fits into a table can be done in different ways. The method I used in this example is described here: http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/

Samstag, 15. Juni 2013

Powershell and vCenter Orchestrator Webservice with Output parameters

Hi,
here is the the script you need to get all output parameters of your vCO workflow when you call it from powershell.
Better you paste it into an editor, because it is very long:

$vmName = $args[0]; #to launch the script from commandline with parameters

if(!($vmName)) # if no paramteres are set, ask for it
    {
        $vmName = read-host "Please Enter a Server Name"
    }


[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$username = "VCOadmin"
$password = "VCOpassword"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))

$webservice = New-WebServiceProxy -uri "http://vcoserver:8280/vmware-vmo-webcontrol/webservice?WSDL"  -Credential $cred
$t = $webservice.getType().namespace

$attributes = New-Object ($t + ".WorkflowTokenAttribute")

$attributes.name = "vmName"
$attributes.value = $vmName
$attributes.type = "String"


#$webservice | Get-member
$wf = $webservice.getWorkflowsWithName("*getHotPlugINfo*","$vmName = $args[0];

if(!($vmName))
    {
        $vmName = read-host "Please Enter ServerName"
    }


$webservice = New-WebServiceProxy -uri "http://VCOserver:8280/vmware-vmo-webcontrol/webservice?WSDL"  -Credential $cred
$t = $webservice.getType().namespace

$attributes = New-Object ($t + ".WorkflowTokenAttribute")

$attributes.name = "vmName"
$attributes.value = $vmName
$attributes.type = "String"

#get all workflows, where the name is like getHotPlugInfo, or what ever your name is
$wf = $webservice.getWorkflowsWithName("*getHotPlugINfo*","VCOadmin","VCOpassword")

#start the vCO workflow by its ID
foreach($i in $wf)

    {
       $infos = New-Object psobject
        if($i.name -eq "getHotplugInfo")
           {
           $resp = $webservice.executeWorkflow($i.id,"VCOadmin","VCOpassword",$attributes)
           $WFid = $resp.id            
           $resp.businessState
           
           do{Start-Sleep -Seconds 2}
           while($webservice.getWorkflowTokenStatus(@($WFid), "VCOadmin","VCOpassword") -eq”running”) #get workflow status until it is finished
           
           $status = $webservice.getWorkflowTokenResult(@($WFid),"VCOadmin","VCOpassword") #get the output parameters of your workflow

                $infos | Add-Member NoteProperty Server $status[0].value
                $infos | Add-Member NoteProperty Memoryhotplug $status[1].value
                $infos | Add-Member NoteProperty CPUHotplug $status[2].value
            
            $infos      
           }
    }

The script is self explaining I think, if you have any questions send me an email.

If you are looking for more information about webservice and vCO visit the vcoportal at http://www.vcoportal.de/

Donnerstag, 17. Januar 2013

Call Powershell Scripts with Parameters

Hello,
often you need to pass parameters when you call your powershell scripts. This is very easy and quickly done.

By passing arguments to your script you create a kind of array of arguments, correct me if I am wrong.

But to use them, you treat them like an array.

To assign a passed argument to a new variable use this:

$var1 = $args[0]
$var2 = $args[1]

very easy, isn't it??

I prefer to call my scripts not directly, because I dont like to write the whole calling command.
The way i prefer is to use command files.

The only thing you need to write into your file is:

powershell.exe -file "<path>" arg1 arg2 arg3 ...

If you want to log all errors type 2> behind your command:

powershell.exe -file "<path>" arg1 arg2 arg3  2> <path>

There could be one hard failure which could make you desperate.
Your script works fine, your call is also fine, but your paramters are not passed to your script. WHY?

It costs me a lot of time, but at the end the failure is hardly hidden :)

The way I name my command files is call_myscript.cmd. This would work.

If you name your command file call_mysscript.ps1.cmd this would also call your script. But it would not pass your parameters. Don't ask me why.

Hope this helps you.

Using Powershell to call a webservice with a complex data type

Hey,
in the last time I often had to implement webservice calls into my powershell scripts. I havent done this very often in the past, so I needed to look for the correct doing on google.

What I found was lots of tutorials how to call a webservice, using the New-WebServiceProxy commandlet. To be honest, this is not satisfying.
What I was looking for is how to pass arguments of a costum types. And this is what I will show you in this blog post. If you see the solution, it is very simple.

Ok lets start with a additional parameter, the credentials.

First we need to build a credentials object:

$username = "admin"
$password = "adminpassword"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))

Next step is to build a variable, which holds the webservice call:

$webservice = New-WebServiceProxy -Uri "http://vco-appliance:8280/vmware-vmo-webcontrol/webservice?WSDL" -Credential $cred
 
The webservice I use in this example is the webservice of the vCenter Orchestrator, a very nice tool to automate your vCenter workflows.

You can browse through your webservice very easy. you just have to pipe your $webservice object to the get-member commandlet -> $webservice | gm

What we need to know at this point is, what kind of namespace is the webservice using. This is important, because we need this to specify the type of our arguments later.
So, how to get the namespace:

$t = $webservice.getType().namespace
#output
$t
 
what you get is something like that:
Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceP
roxy1vmo_webcontrol_webservice_WSDL
 
Now our basement is build, lets create the arguments we want to pass to the webservice later:
$attributes = New-Object ($t + ".WorkflowTokenAttribute")
$attributes.name = "input"
$attributes.value = " "
$attributes.type = "String"

Maybe you ask now, how does he know that he has to use "WorkflowTokenAttribute" as type. I forget to say WorkflowTokenAttribute is the type of our object.

You can verify your object type by typing:

$attributes | gm  (gm is the short form of get-member)
or
$webservice.getType()

This is easy, the right way would be to have look into the WSDL file. The easier way is to use the error message of powershell. So run your script, passing all arguments you want to pass just as a string.
You will get an error message like that:

Cannot convert argument "3", with value: "123456", for "executeWorkflow" to type "Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1vmo_
webcontrol_webservice_WSDL.WorkflowTokenAttribute[]": "Cannot convert the "123456" value of type "System.String" to type Microsoft.PowerShell.Commands.NewWebserviceProxy
.AutogeneratedTypes.WebServiceProxy1vmo_webcontrol_webservice_WSDL.WorkflowTokenAttri
bute[]"."
As you can see powershell tells us, what kind of type it expects.

Now you need to know what parameters should be included in our new object, maybe you know it, have a look to the wsdl, or the way I prefer: Import the webservice into a tool which shows you the content of the wsdl. I use wavemaker to do this.

Wavemaker is cool tool to build your own website using webservices. It is very easy. Everybody will be surprised when you create a selfservice portal within 30min ;). If you are intrested in the piece of software, just download it, it's free.

 Back to our topic:

The last step is to call your webservice with all objects we build until now:
$resp = $webservice.executeWorkflow($parameter1,"vCOuser","userPW",$attributes)
$resp means respons, I use the variable to check if my webservice call was successfull

in some webservices you will get a returncode, status, name, id and many others.

For now we are done. A complete script could look like this:

$username = "admin"
$password = "adminPW"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
$webservice = New-WebServiceProxy -uri "http://vCO-appliance:8280/vmware-vmo-webcontrol/webservice?WSDL"  -Credential $cred
$t = $webservice.getType().namespace
$attributes = New-Object ($t + ".WorkflowTokenAttribute")
$attributes.name = "input"
$attributes.value = " "
$attributes.type = "String"
$resp = $webservice.getWorkflowsWithName("MyWorkflow*","vCOUser","userPW")
foreach( $element in $resp)
    {
        $element.id + "`t" + $element.name
   
$resp = $webservice.executeWorkflow($element,"vCOuser","userPW",$attributes)
$Workflowid = $resp.id
$status = $webservice.getWorkflowTokenStatus($Workflowid,"vCOuser","userPW")
$status
while ( $status -eq "running")
    {
        $status = $webservice.getWorkflowTokenStatus($Workflowid ,"vCOuser","userPW")
        $status
        "running"
    }
   
}

This script gets all workflows, which are starting in its name with "MyWorkflow" and starts it in a loop.

You also can build objects of a complex type:
you need this for example to call a HP service manager webservice.
$t = $webservice.GetType().Namespace
$myComplextype = new-object ($t + ".Request")
$instance = new-object ($t + ".InstanceType")
$model = new-object ($t + ".ModelType")
$keys = new-object ($t + ".KeysType")
$changeID = new-object ($t + ".StringType")

$changeID.Value = "1234"
$keys.ChangeID = $changeID
$model.instance = $instance
$model.keys = $keys

$myComplextype.model = $m

Mittwoch, 21. März 2012

PowerShell: Create DNS Alias Entry

This Script will help you to automate your DNS-registration. If you have 2 NICs installed in your system, maybe you dont want both to register in the DNS. What you do is to create manually an entry for your NIC with an alias.
I created this script to detect the NIC with a special IP-address, prove whether it has an A-record and a PTR-record. If not it will create it:
I did some comments into the code, for any other questions just ask.

"Create DNS backup entry" > "c:\temp\DNSentry.txt"
get-date >> "c:\temp\DNSentry.txt"

## check DNS server contactable
  if (-not (Test-Connection -ComputerName <your DNS-Server> -quiet )){"DNS server not found" >> "c:\temp\DNSentry.txt"}
    else
{
"DNS Server is reachable"  >> "c:\temp\DNSentry.txt"
##get FQDN
$computersystem = get-WmiObject -Class Win32_computersystem
$systemname = ($computersystem).name + "<Suffix>" + "." + ($computersystem).Domain
"Systemname: " + $systemname  >> "c:\temp\DNSentry.txt"
##get the ip-address of your NIC
$NICadapter = @()
$NICadapter += gwmi win32_networkadapterconfiguration | ? { $_.IPaddress -like "*192.168*"}
##check if there is a backup NIC
##if not, skip everything
$checkNIC = gwmi win32_networkadapterconfiguration | ? { $_.IPaddress -like "192.168*"}
if($checkNIC){
foreach($element in $NICadapter){
##revert IP and trim
$IParray = $element.IPaddress -split "\."
$ipaddress = $element.IPaddress
break
}
$revertipaddress = $iparray[3] + "." +$iparray[2] + "." +$iparray[1]
#$revertipaddress
"NIC IP:" + $ipaddress  >> "c:\temp\DNSentry.txt"
##Check Entry if exists
$Arec = Get-WmiObject -ComputerName <your DNS-Server> -Namespace ‘root\MicrosoftDNS’ -Class MicrosoftDNS_ATYPE -filter 'ContainerName = "domain.net"' | ? {$_.OwnerName -like "$systemname" } # | select -first 1
$PTRrec = Get-WmiObject -ComputerName <your DNS-Server> -Namespace ‘root\MicrosoftDNS’ -Class MicrosoftDNS_PTRTYPE -filter 'ContainerName = "10.in-addr.arpa"' | ? {$_.OwnerName -like $revertipaddress +"*"} # | select -first 1
$DNScheck = 4

""  >> "c:\temp\DNSentry.txt"
"Checking A-Record..."  >> "c:\temp\DNSentry.txt"
""  >> "c:\temp\DNSentry.txt"
IF($Arec)
        {"There is an existing A-Record for " + $systemname >> "c:\temp\DNSentry.txt"
         "Aborting!" >> "c:\temp\DNSentry.txt"
         exit              
        }
      else
        {"there is no A-Record" >> "c:\temp\DNSentry.txt"
        }
""  >> "c:\temp\DNSentry.txt"       
"Checking PTR-Record..."  >> "c:\temp\DNSentry.txt"
        
IF($PTRrec)
        {"There is an existing PTR-Record for " + $systemname >> "c:\temp\DNSentry.txt"
         "Aborting!" >> "c:\temp\DNSentry.txt"
         exit  
        }
      else
        {"there is no PTR-Record" >> "c:\temp\DNSentry.txt"
        }
"Test"
##A-Record
##Create WMI-Class
$rec = [Wmiclass]'\\<your DNS-Server>\root\MicrosoftDNS:MicrosoftDNS_AType'
#set properties
$server = "<your DNS-Server>.domain.net"
$zone = "domain.net"
$name = "$systemname"
$class = 1
$TTL = 1200
$address = "$ipaddress"
##Create A-Record
$rec.CreateInstanceFromPropertyData($server,$zone,$name,$class,$TTL,$address)

##PTR-Record
##Create WMI-Class
$rec = [Wmiclass]'\\<your DNS-Server>\root\MicrosoftDNS:MicrosoftDNS_PTRType'
#$rec | gm
##set properties
$server = "<your DNS-Server>.domain.net"
$zone = "xy.in-addr.arpa"
$name = "$revertipaddress"
$class = 1
$TTL = 1200
$address = "$systemname"
##Create PTR-Record
$rec.CreateInstanceFromPropertyData($server,$zone,$name,$class,$TTL,$address)
}
else
{"There is no NIC" >> "c:\temp\DNSentry.txt"}
}

##Check Entry
$Arec = Get-WmiObject -ComputerName <your DNS-Server> -Namespace ‘root\MicrosoftDNS’ -Class MicrosoftDNS_ATYPE -filter 'ContainerName = "domain.net"' | ? {$_.OwnerName -like "$systemname" } # | select -first 1
$PTRrec = Get-WmiObject -ComputerName <your DNS-Server> -Namespace ‘root\MicrosoftDNS’ -Class MicrosoftDNS_PTRTYPE -filter 'ContainerName = "10.in-addr.arpa"' | ? {$_.OwnerName -like $revertipaddress +"*"} # | select -first 1
$DNScheck = 4

""  >> "c:\temp\DNSentry.txt"
"A-Record"  >> "c:\temp\DNSentry.txt"
""  >> "c:\temp\DNSentry.txt"
IF($Arec)
        {$Arec >> "c:\temp\DNSentry.txt"}
      else
        {"there is no A-Record" >> "c:\temp\DNSentry.txt"}
""  >> "c:\temp\DNSentry.txt"       
"PTR-Record"  >> "c:\temp\DNSentry.txt"
        
IF($PTRrec)
        {$PTRrec >> "c:\temp\DNSentry.txt"}
      else
        {"there is no PTR-Record" >> "c:\temp\DNSentry.txt"}

Donnerstag, 23. Februar 2012

Rename your network adapter using Powershell and netsh

Often I have the problem that my network adapters are labeled wrong. So I want to rename them. The easiest way to rename your adapter is to use netsh. But if you want to you netsh you are limited to one adapter. What would you do if you want to do this dynamicly and for more than one adapter, doesn't matter how much NIC are installed. Yes, use powershell!!!!


In this example I will show you how to get the name of a network adapter with a specific ip address.
First you have to get all of your adapters by using WMI. You can find all installed adpaters in the win32_networkadapter and win32_networkadapterconfiguration classes.
We start to get all instances of the win32_networkadapterconfiguration:
Type gwmi win32_networkadapterconfiguration


you will get more than 1 result, also if you only have one network card.

The network interface I want to change is "Atheros AR5B97 Wireless Network Adapter".
What we need is the index of your network interface, so we have pipe our output into a where-object:
Type  gwmi win32_networkadapterconfiguration | ? {$_.ipaddress -like "*192.168*"}
Instead of my *192.168* you can type your own ip address.


we need this later again, so we put this command into a variable. and let us show the index:


If you have more than one interface with ip like "192.168*" this will fail, then you have to use a foreach loop.


The rest is easy now. You have to use the index of your interface to get the networkconnectionID from the win32_networkadapter class:
Type: 
 $networkadapterID = gwmi win32_networkadapter | ? { $_.index -eq ($networkadapter).index}
 ($networkadapterID).netconnectionID

Your Output will be the same as it is in your control center:
To use netsh you have to know how it is labeled.
The netsh command to rename your network inerface is:
netsh interface set interface "<your interface name>" newname="NewName"


How to include this into powershell?
This is also very simple:
First you have to put this command into a variable:
Type:   
$input = @"
interface set interface "$oldinterfacename" newname="NewName"
"@
Second and last step is to pipe this input into netsh:
Type: $input | netsh
 You are finished now.




To give you one more example, I have used this commands for more than one interface.


$adapter = gwmi win32_networkadapterconfiguration | ? { $_.IPaddress -like "*192.168*"}
$i = 1
foreach($element in $adapter){
$adapterindex = $element.index
$newname = "Adapter"+$i
$adapterID = gwmi win32_networkadapter | ?{$_.index -eq $adapterindex}
$adapter = ($adapterID).NetConnectionID
    $input = @"
interface set interface "$adapter" newname="$newname"
exit
"@
$input
$input | netsh
$i++
}

I hope this will help you, and please forgive my bad teaching skills. this is my first time :D