Quantcast
Channel: Windows PowerShell forum
Viewing all 21975 articles
Browse latest View live

Array and variables

$
0
0

Hi,

I have those variable definition as you can see the msi names are appearing twice.

 Set-variable -name Arr_MSI -visibility public -scope script `
        -Value @("\WordQ4S_NA_FR\WordQ\WordQ 4.msi",  `"\WordQ4S_NA_FR\AcapelaCore\Acapela Text to Speech for WordQ 4 (Core).msi",  `"\WordQ4S_NA_FR\AcapelaNA\Acapela Text to Speech for WordQ 4(North America).msi",  `"\WordQ4S_NA_FR\AcapelaCFR\Acapela Text-to-Speech for WordQ 4(Canadian French).msi" `
               )
		set-variable -name Var_Prog1 -visibility public -Scope Script `
		-Value @("Execute-MSI -Action Install -Path `"$Var_SourceFiles\WordQ4S_NA_FR\WordQ\WordQ 4.msi`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\WordQ4S_NA_FR\AcapelaCore\Acapela Text to Speech for WordQ 4 (Core).msi`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\WordQ4S_NA_FR\AcapelaNA\Acapela Text to Speech for WordQ 4(North America).msi`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\WordQ4S_NA_FR\AcapelaCFR\Acapela Text-to-Speech for WordQ 4(Canadian French).msi`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"" `

So I tried replacing the MSI names with their values from the array.

Set-variable -name Arr_MSI -visibility public -scope script `
        -Value @("\WordQ4S_NA_FR\WordQ\WordQ 4.msi",  `"\WordQ4S_NA_FR\AcapelaCore\Acapela Text to Speech for WordQ 4 (Core).msi",  `"\WordQ4S_NA_FR\AcapelaNA\Acapela Text to Speech for WordQ 4(North America).msi",  `"\WordQ4S_NA_FR\AcapelaCFR\Acapela Text-to-Speech for WordQ 4(Canadian French).msi" `
               )
		set-variable -name Var_Prog1 -visibility public -Scope Script `
		-Value @("Execute-MSI -Action Install -Path `"$Var_SourceFiles\$Arr_MSI[0]`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\$Arr_MSI[1]`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\$Arr_MSI[2].msi`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"",  `"Execute-MSI -Action Install -Path `"$Var_SourceFiles\$Arr_MSI[3]`" -Parameters `"ALLUSERS=1 /qn`" -LogName `"$var_PackageLongName`"" `
               )

But it does seem breaking the array :)

What am I missing?

Thanks,


WSUS Updates with powershell from reomte workstation/vm

$
0
0

Good morning, 

I am fairly new to Powershell scripting, and this is my first post to this forum. Anyway, I've been trying to find a way to manage WSUS assigned Windows updates. Basically, listing and installing assigned updates from one PS session while on my Windows 7 vm would be ideal, avoiding logging into domain controllers, veeam backup servers, etc, several times for patching. 

So far I've been working on this:

1) Invoke-Command  {ipmo \\file-server\share\scripts\WSUS\PSWindowsUpdate}   This is used to import Windows Update modules that I found here: 

https://blogs.technet.microsoft.com/heyscriptingguy/2012/11/08/use-a-powershell-module-to-run-windows-update/

Invoke-Command -Session $s {Get-WUlist}      This works without incident when run remotely on a Win 2008 R2 server, providing a listing of updates. 

2) Invoke-Command  {Get-WUInstall -AcceptAll -verbose -Confirm:$TRUE}
WARNING: Support local instance only, Continue...
VERBOSE: Connecting to Windows Server Update Service server. Please wait...
VERBOSE: Found [1] Updates in pre search criteria
VERBOSE: Found [1] Updates in post search criteria

When running this module the script will hang and not install the one assigned update applied by WSUS to this particular server.

Any help or direction is appreciated.

Thanks 

 

Not getting output in proper CSV/text when using cmdlet Export-CSV or Convertto-CSV | Out-File.

$
0
0

May be I am missing some basics, here is a small example.

Get-DHCPServerInDC | FL -Property DNSName | Export-CSV -Path DHCPServer.CSV 

And I am getting some unformatted output.

How to get / convert this to a formatted string or text?

Thanks in advance.

Roushan

Powershell - exporting users with numbered email addresses

$
0
0

Hi all,

I'm trying to export my users list, but the users email addresses are numbered with a sequential 8 digit address. For example 15951478@domain.com.au. I used the following script and was able to export most of them until it crashed. 

Get-Recipient -ResultSize Unlimited | select DisplayName,RecipientType,EmailAddresses | Export-Csv "c:\email-recipients.csv"

Is there a way i can continue the export but from 15951478@domain.com.au onwards? instead of having to start it again, as it keeps crashing (quite a large database). 

Any help is appreciated :) 


Add Windows installer sourcelist

$
0
0

Hi,

I need add some sourcelist to Windows installer product.

In vbscript, I was able doing this:

productcode = "{9017040C-6000-11D3-8CFE-0050048383C9}" addsource = "\\xxx\install$\Trousses\Frontpage2002fr_v3\Sources"

 Dim installer2 : Set installer2 = Nothing Set installer2 = Wscript.CreateObject("WindowsInstaller.Installer") Wscript.echo "Setting Path for: " & productcode & " to " & addsource  rc = installer2.AddSource(productcode,"",addsource)


With PowerShell, is it possible doing the samething or better? I don't want to add some Windows installer module.

Thanks,

Is this a [datetime] bug ?

$
0
0

Hi,

Please helo if I am doing something wrong here. When i use the simple datetime data type to variable it returns the wrong year. But if I do [datetime]::FromFiletime() then the correct year is returned.

PPS M:\> [int64]$abcd = (get-aduser ramesh -Properties lastlogon).lastlogon

PS M:\> [datetime]::FromFiletime($abcd)

14 September 2016 08:48:23

PS M:\> [datetime]$abcd

14 September 0416 07:48:23

PS M:\> ([datetime]$abcd).ToShortDateString()
14/09/0416

PS M:\> ([datetime]$abcd).ToString('dd/MM/yyyy')
14/09/0416

PS M:\> [datetime](get-aduser ramesh -Properties lastlogon).lastlogon

14 September 0416 07:48:23

Read User Attrib from CSV file more than once!

$
0
0

Hi,

I'm trying to write script as follows:

$Users = Import-CSV -Path "C:\UserList.csv"
ForEach ($user in $Users) {

Do

$SamUser = $user.sAMAccountName1

While (Get-ADUser -Filter {sAMAccountName -Like $SamUser})

New-ADUser ... }

My question:

I have 8 combinations of First & Last names of each user in the CSV file. How can I change the column name for each user to check the existence of the sAMAccountName in AD?

TIA

How can I redirect output from Start-Process back to the main console so Start-Transcript can catch the output?

$
0
0

I've been searching high and low and I can't get this to work.  We use robocopy ALOT. So for the less CLI using people, I made a front end for it using powershell and forms.  The user is allowed to select a from directory and a list of files and then a to directory.  When the user presses on transfer it builds a run string namely consisting of:

       $strToRun = "`"$strFromPath`" `"$strToPath`""

        $lstFiles.Items.ForEach({
            $strToRun += " `"$_`""
        })

        $strToRun += " & PAUSE"
        Start-Process cmd "/c $strToRun"
Since the users are opening the PS1 script via a cmd script, to bypass executionpolicies, I make the main console hidden, and then the form opens up.  Transcript is still running and it writes to the transcript file, whatever comes out on the "hidden" console window.  So when the user clicks on Transfer, it runs the last line of code I input above.  I'm trying to catch this output so it saves it to the transcript. I like to keep track of everything including any file transfers that need to take place for app releases, this way, proof of execution can be done by sending them the transcript.


Powershell

$
0
0
I am trying to install powershell I am told to type powershell in the search textbox and then click "Using windows powershell for daily tasks" but can not find that action?

suppress output

$
0
0

I have this code:

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty 


When I run this it works but on any 32-bit system it will also output an error.  

Get-ChildItem : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Filter'. Specified method is not supported.
At line:1 char:29

How do you suppress that so it is never seen?  I tried -HIDDEN but that did not work.  


mqh7

How do I use Powershell to issue Telnet commands (Windows Server 2012/R2?

$
0
0

I have a windows 2012 R2 server running a game for my kids and their friends. this game supports Telnet for admin stuff like shutdown, etc.

the game is buggy and needs to be restarted every 3 to 6 hours and I would like to schedule this using a powershell script on my server. 

what I do today:

1. start Putty on remote machine.

2. connect to server IP, Port

3. get prompted for a password (no username).  Enter Password

4. issue a list player command to see who is on more of an FYI but would like to capture this info to a log file.

5. issue a command Say "Server restarting Shortly". I wait a few minutes

6. issue a "shutdown" command that cause the server to shutdown and restart and kills my telnet session.

7. a few minutes later I reconnect to make sure it is up.

I do this from my mobile app or my Surface and would really like to just have a powershell script on the server running. 

thanks!

Permissions issue when running script as Scheduled Task

$
0
0

I'm trying to run a script within Exchange shell as a scheduled task and need some assistance with how to overcome what I believe is a permissions issue. Pertinent information:

  • Exchange 2010 SP3
  • Powershell 4.0
  • Server 2008 R2 SP1
  • Running this script on a machine with the Exchange management tools installed
  • The script functions properly when run using my own user account
  • The script functions properly when I do a Run-As of Exchange Shell using the service account I am trying to run the Scheduled Task with.
  • In an attempt to troubleshoot the issue I've gone so far as to elevate the service account to an Organization Administrator, which had no effect.
  • I've configured the Scheduled Task per instructions at http://social.technet.microsoft.com/wiki/contents/articles/23150.how-to-use-task-scheduler-for-exchange-scripts.aspx. The only deviations from their instructions have to do with the command line arguments; I've omitted the "-Version 2.0" switch and added "-executionpolicy Bypass"
  • Execution problems when run as a scheduled task include HTTP 400 failures of invoke-webrequest (Unknown but not expected to be due to some of the operations to construct the headers or body of the request), failures of search-mailbox to execute properly (items are not found when they should have been), failure of other processes such as get-messagetrackinglog to execute when they should have
  • I've tried running two copies of this script at the same time - one as a scheduled task under the service account and one in an interactive PS session under my own creds and had it work perfectly. That's how I am confident that some of the above command failures (previous bullet point) hould instead execute properly.
  • Based on my troubleshooting I don't think this is an Exchange issue so much as it's an issue with Task Scheduler handling the execution of this script.
  • I've copied the script below. In case it's helpful the script works by querying the API of our organization's spam provider. It grabs a list of malicious messages it knows were delivered to user mailboxes, runs a Message Tracking search, and then uses search-mailbox to delete messages that are found. There's a bit of logic and some other functionality but in broad strokes that's what it does. It's designed to run in an endless loop (hence the do-until 2 -lt 1). I'm happy to answer any questions about it that might be helpful to solving this problem.
  • Finally, please excuse my poor Powershell coding; I'm self-taught and I'm sure it shows.

# NOTE: Do not exceed 1800 requests in a 24 hour period (1.25 requests per minute or one request every 48 seconds) for the TAP API or Proofpoint will throttle your requests.
# Also note that clicks/permitted requests are throttled separately from all other requests (i.e. you get 1800 clicks/permitted requests and 1800 requests of all other kinds per 24 hours)

#$auth = "${username}:${password}"

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1 #The script is dot sourced here
Connect-ExchangeServer -auto

$script:errorhappened = $false


function get-credsfromsecretserver
	{
	param
		(
		[parameter(Mandatory=$true)][String[]]$secretID,
		[parameter(Mandatory=$false)][string]$specifyusernameforcredobject = $false
		)

	$where = 'https://mywebservicetogetcredentialsfrom/page.asmx'
	$ws = New-WebServiceProxy -uri $where -UseDefaultCredential
	$wsResult = $ws.GetSecret("$secretId")
	$password = $wsResult.Secret.Items[2].Value.tostring() | Convertto-securestring -asplaintext -force
	$wsResult.Secret.Items[2].Value = "See variable `$password"

	if ($wsResult.Errors.length -gt 0)
		{
		$wsResult.Errors[0]
		}
	else
		{
		$SSOutput = @()
	        $username = $wsResult.Secret.Items[1].Value.tostring()
		$SSOutput += @{'SSUsername'="$username"}
		$SSOutput += @{'SSPassword'=$password}

		if ($specifyusernameforcredobject -ne $false)
				{
				$credobjusername = $specifyusernameforcredobject
				}
			else
				{
				$credobjusername = $username
				}
		$creds = New-Object System.Management.Automation.PSCredential $credobjusername,$password
		$SSOutput += @{'SSCredObject'=$creds}
		}
	return $SSOutput
	}


function handle-errors
    {
    $script:errorhappened = $true

    foreach ($errorobject in $error)
        {
        # this is to exclude the standard silent error generated whenever you connect to remote Powershell. We don't want it included in logs.
        if (-not ($errorobject.exception.message -eq "Cannot find path 'HKLM:\Software\microsoft\ExchangeServer\v14\CentralAdmin' because it does not exist."))
            {
            $logfilemessage = $errorobject.exception.message + " SCRIPT LINE " + $errorobject.invocationinfo.scriptlinenumber + " CHAR " + $errorobject.invocationinfo.OffsetInLine + ". COMMAND: " + $errorobject.invocationinfo.line.trim() + ". ERRORTYPE: " + $errorobject.exception.gettype().fullname
            update-logfile -logfile $targetlogfile -eventtype error -message $logfilemessage
            }
        }
    $error.clear()
    }

function maint-logfiles
    {
    try
        {
    if ((get-childitem "c:\server tools\scripts\tapdeletionlogs\*" -include "tap*.txt").count -gt 0)
        {
        $mostrecentlogfile = get-childitem "c:\server tools\scripts\tapdeletionlogs\*" -include "tap*.txt" | sort lastwritetime -desc | select -first 1
        $mostrecentlogfiledate = $mostrecentlogfile.name.tostring().replace("TAPScript_","").replace(".txt","").trim()
        $mostrecentlogfiledate = [datetime]::parseexact($mostrecentlogfiledate,'MM-dd-yy',$null)
        $mostrecentlogfiledate = get-date $mostrecentlogfiledate -uFormat "%m-%d-%y"

        if ((get-date -UFormat "%m-%d-%y") -ne $mostrecentlogfiledate)
            {
            $tempfiledate = get-date -UFormat "%m-%d-%y"
            $tempfilename = "c:\server tools\scripts\tapdeletionlogs\TAPScript_" + $tempfiledate + ".txt""Log fields for search actions: Timestamp, MessageID, Target Mailbox DisplayName, Status Message" | out-file -filepath $tempfilename
            $targetlogfile = $tempfilename
            }
        else
            {
            $targetlogfile = $mostrecentlogfile.VersionInfo.FileName.tostring().trim()
            }
        }
    else
        {
        $tempfiledate = get-date -UFormat "%m-%d-%y"
        $tempfilename = "c:\server tools\scripts\tapdeletionlogs\TAPScript_" + $tempfiledate + ".txt""Log fields for search actions: Timestamp, MessageID, Target Mailbox DisplayName, Status Message" | out-file -filepath $tempfilename
        $targetlogfile = $tempfilename
        }
    return $targetlogfile
        }
    catch
        {
        handle-errors
        }
    }

function update-logfile
    {
    param
        (
        [parameter(mandatory=$true)][string]$logfile,
        [parameter(mandatory=$true)][string][validateset("info","warn","error")][string]$eventtype,
        [parameter(mandatory=$true)][string]$message
        )
    try
        {
    $loglinetimestamp = (get-date -uformat "%D_%T_GMT%Z") + "  "
    $eventtypetext = "[" + $eventtype.toupper() + "]  "
    $logline = $loglinetimestamp + $eventtypetext + $message
    try
        {
        add-content -path $logfile -value $logline
        }
    catch
        {
        $message1 = $null
        $message1 = $loglinetimestamp + "[ERROR]  Error writing to logfile! " + $error[0].message + $error[0].exception.message
        add-content -path $logfile -value $message1
        write-host -ForegroundColor yellow $message1
        }
        }
    catch
        {
        handle-errors
        }
    }

try
    {

    # Logfile folder setup and maintenance
    if (-not (test-path "c:\server tools\scripts\TAPDeletionLogs"))
        {
        new-item -path "c:\server tools\scripts" -ItemType directory -name "TAPDeletionLogs"
        }

    $targetlogfile = maint-logfiles

    update-logfile -logfile $targetlogfile -eventtype info -message "Script Launched"

    }
catch
    {
    handle-errors
    }

try
    {
    $SSCreds = get-credsfromsecretserver -secretid 8395

    $username = $SSCreds.sscredobject.UserName
    $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SSCreds.SSPassword))
    $encodedAuth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
    $basicAuthValue = "Basic $encodedAuth"
    $headers = @{Authorization = $basicAuthValue}
    }
catch
    {
    handle-errors
    }

do
    {
    try
        {
    # Record the current time for interval calculation and also save it to file to record last execution time.
    # This is important because if the server reboots or the script is disrupted otherwise for more than five minutes we can pick up where we left off.
    $now = get-date

    $targetlogfile = maint-logfiles


    # Grab the last-execution time from file if it's present.
    if (test-path "c:\Server Tools\Scripts\TAP_LastExecTime.txt")
        {
        $lastexectime = get-content "c:\Server Tools\Scripts\TAP_LastExecTime.txt" | out-string
        $lastexectime = get-date $lastexectime
        }


    # If it's been more than an hour since the last run time then set "Now" to be an hour after the last run time. PP will only give us an hour of data, max.
    if ($lastexectime -lt ($now.addhours(-1)))
        {
        # If it's been more than two hours since last run then we're outside the time range of data PP will return to us. Set the Last Exec time to two hours ago and Now to an hour after that.
        # Pad those times a bit to account for any discrepancies with Proofpoint's clocks and ours.
        if ($lastexectime -lt ($now.addhours(-2)))
            {
            $lastexectime = $now.addminutes(-115)
            $now = $lastexectime.addminutes(55)
            }
        # In this case it's been more than one hour but less than two. Leave Last Exec as it is and set Now to one hour after it. We'll pick up the difference on the next go-around.
        # Pad those times a bit to account for any discrepancies with Proofpoint's clocks and ours.
        else
            {
            $now = (get-date $lastexectime).addminutes(55)
            }
        }

    # Whatever we ended up setting Now to it will become our new Last Exec time for the next time thru the script. Save it as such.
    $now | out-file "c:\Server Tools\Scripts\TAP_LastExecTime.txt"

    $interval = (get-date $lastexectime -format yyyy-MM-ddTHH:mm:sszz00) + "/" + (get-date $now -format yyyy-MM-ddTHH:mm:sszz00)

    $URI = "https://mytargetwebserver?format=json&interval=$interval"
    $content = $null
    $response = $null

    $response = invoke-webrequest -uri $URI -Method GET -Headers $Headers
    $content = $response.content | convertfrom-json

    if ($content.messagesdelivered.count -gt 0)
        {
        $logfilemessage = $content.messagesdelivered.count.tostring() + " known-bad messages delivered. Beginning deletions."
        update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage

        # Message Tracking Search
        $results = @()
        $messages = $null
        $messages = $content.messagesdelivered | select -unique messageid

        foreach ($message in $messages)
            {
            get-transportserver | get-messagetrackinglog -MessageId $message.messageid -EventID DELIVER | % {$results += $_}
            }

        # Expand out the list so we have one message per line
        $output = @()

        foreach ($result in $results)
            {
            $thissender = $null
            $thiscombo = $null
            $thissender = $result.sender
            if ($result.recipients.count -gt 1)
                {
                foreach ($recipient in $result.recipients)
                    {
	                # If you need to add additional message metadata with which to search (sent time, for instance) add properties below.
                    $thiscombo = new-object psobject
                    $thiscombo | add-member noteproperty Sender($thissender)
                    $thiscombo | add-member noteproperty Recipient($recipient)
	                $thiscombo | add-member noteproperty Subject($result.messagesubject)
	                $thiscombo | add-member noteproperty Timestamp($result.timestamp)
                    $thiscombo | add-member noteproperty MessageID($result.messageid)
                    $output += $thiscombo
                    }
                }
            else
                {
	            # If you need to add additional message metadata with which to search (sent time, for instance) add properties below.
                $thiscombo = new-object psobject
                $thiscombo | add-member noteproperty Sender($thissender)
                $thiscombo | add-member noteproperty Recipient($result.recipients)
	            $thiscombo | add-member noteproperty Subject($result.messagesubject)
	            $thiscombo | add-member noteproperty Timestamp($result.timestamp)
                $thiscombo | add-member noteproperty MessageID($result.messageid)
                $output += $thiscombo
                }
            }

        if (($output[0].sender -ne $null) -AND ($output[0].recipient -ne $null))
            {
            $mailboxes = $output
            $today = get-date -format MM-dd-yyyy
            $targetfolder = "TAP Deletions/Deletions_" + $today

            $logquerytext = @()

            foreach ($mailbox in $mailboxes)
                {
                $thissender = ($mailbox.sender | out-string).trim()
                $thisperson = ($mailbox.recipient | out-string).trim()
                $thistimestamp = ($mailbox.timestamp | get-date -format "MM/dd/yyyy" | out-string).trim()
                $thissubject = ($mailbox.subject | out-string).trim()

                # Because we're passing variables into the search query we have to create the query itself as a string, enclosing it in single quotes as well. The below two lines do that.

######################################################################################################
# Modify the below deletion search if you want to search on more than subject, sent date and sender. #
######################################################################################################
                # Modify the next lines if you want to change your deletion parameters manually. If adding a variable you'll need to repeat the process of tacking it on to the end of the string as per below.
                $query = 'received:' + $thistimestamp
                $query = $query + ' AND subject:"' + $thissubject
                $query = $query + '" AND from:"' + $thissender
                $query = $query + '"'
                # You may wish to change the target mailbox or target folder as needed.

                $logquerytext += $query
                $theseresults = search-mailbox -identity $thisperson -searchquery $query -targetmailbox searchuser -targetfolder $targetfolder -force -LogLevel Full -deletecontent -searchdumpster

                $messagebody = $null
                $messagesubject = $null
                $tapmessageinfo = $null

                $tapmessageinfo = $content.messagesdelivered | where {$_.recipient -eq $thisperson -AND $_.MessageID -eq $mailbox.messageid}

                if ($theseresults.resultitemscount -gt 0)
                    {
                    # OK we found and removed messages. Report on it.
                    $theseresults | add-member noteproperty SearchQuery($query)
                    $messagebody = "The following messages from TAP notifications were found and successfully removed from user mailboxes:"
                    $messagebody = $messagebody + ($mailbox | out-string) + ($theseresults | out-string) + ($tapmessageinfo | out-string)
                    $messagesubject = "TAP - Messages Deleted Successfully"
                    $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Initial search found and deleted " + $theseresults.resultitemscount + " messages"
                    update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage
                    }

                else
                    {
                    # We didn't find anything.

                    $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Initial search found " + $theseresults.resultitemscount + " messages"
                    update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage

                    # Search on just sent date and sender's address and try again. Exclude OurDomain  addresses.
                    # The first time through we won't actually delete or copy anything; just see how many results we get to find out if we should remove stuff or not.
                    $query = $null
                    $query = 'received:' + $thistimestamp
                    $query = $query + ' AND from:"' + $thissender
                    $query = $query + '"'

                    $2ndsearchresults = $null
                    $2ndsearchresults = search-mailbox -identity $thisperson -searchquery $query -targetmailbox searchuser -targetfolder $targetfolder -force -LogLevel Full -LogOnly -searchdumpster

                    # Check the second search results and see how many we turned up. If five or less then go ahead and actually delete them, otherwise hold off.
                    if ($2ndsearchresults.resultitemscount -lt 6 -AND $2ndsearchresults.resultitemscount -ge 1 -AND $thissender -notmatch "@MyDomain.com")
                        {
                        $2ndsearchdeleteresults = $null
                        $2ndsearchdeleteresults = search-mailbox -identity $thisperson -searchquery $query -targetmailbox searchuser -targetfolder $targetfolder -force -LogLevel Full -deletecontent -searchdumpster
                        $2ndsearchdeleteresults | add-member noteproperty SearchQuery($query)
                        $messagebody = "The following message from TAP notifications were found and successfully removed from a user mailbox:"
                        $messagebody = $messagebody + ($mailbox | out-string) + ($2ndsearchdeleteresults | out-string) + ($tapmessageinfo | out-string)
                        $messagesubject = "TAP - Messages Deleted Successfully"

                        $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Second search successfully deleted " + $2ndsearchdeleteresults.resultitemscount + " messages"
                        update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage
                        }
                    # In this instance the second search still didn't find anything the second time around.
                    elseif ($2ndsearchresults.resultitemscount -eq 0 -AND $thissender -notmatch "@MyDomain.com")
                        {
                        $2ndsearchresults | add-member noteproperty SearchQuery($query)
                        $messagebody = "The following message from TAP notifications could not be automatically removed from the user's mailbox because a search for it failed:"
                        $messagebody = $messagebody + ($mailbox | out-string) + ($2ndsearchdeleteresults | out-string) + ($tapmessageinfo | out-string)
                        $messagesubject = "TAP - Message Deletion Failure"

                        $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Second search found " + $2ndsearchresults.resultitemscount + " messages"
                        update-logfile -logfile $targetlogfile -eventtype warn -message $logfilemessage

                        }
                    # And in this case the second search found too many items so we didn't delete anything.
                    elseif ($2ndsearchresults.resultitemscount -gt 5 -AND $thissender -notmatch "@MyDomain.com")
                        {
                        $2ndsearchresults | add-member noteproperty SearchQuery($query)
                        $messagebody = "The following message from TAP notifications was not automatically removed from the user's mailbox because more than five messages would have been deleted:"
                        $messagebody = $messagebody + ($mailbox | out-string) + ($2ndsearchresults | out-string) + ($tapmessageinfo | out-string)
                        $messagesubject = "TAP - Message Deletion Failure"

                        $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Second search found " + $2ndsearchresults.resultitemscount + " messages. Too many to delete so no aciton was taken."
                        update-logfile -logfile $targetlogfile -eventtype warn -message $logfilemessage

                        }
                    # We didn't find anything in the first search and the sender's address is a MyDomain.com address - probably spoofed.
                    # Just send the results of the second, log-only search but don't delete or copy anything.
                    if ($theseresults.resultitemscount -lt 1 -AND $thissender -match "@MyDomain.com")
                        {
                        $2ndsearchresults | add-member noteproperty SearchQuery($query)
                        $messagebody = "The following messages from TAP notifications were not automatically removed from the user's mailbox. The initial search (including subject line) failed to locate any messages. A search by received date and sender's address was run and the results appear below. No messages were deleted because the FROM address was a MyDomain.com address. As such the risk of deleting legitemate messages is too great."
                        $messagebody = $messagebody + ($mailbox | out-string) + ($2ndsearchresults | out-string) + ($tapmessageinfo | out-string)
                        $messagesubject = "TAP - Message Deletion Failure"

                        $logfilemessage = $mailbox.messageid.tostring() + "  " + $theseresults.displayname.tostring() + "  " + "Second search found " + $2ndsearchresults.resultitemscount + " messages but the sender has a MyDomain.com address so no action was taken."
                        update-logfile -logfile $targetlogfile -eventtype warn -message $logfilemessage

                        }

                    }
                # Here's where we actually send the notification message based on the settings we chose above.
                Send-MailMessage -SmtpServer smtp.MyDomain.com -From johndoe4@MyDomain.com -To johndoe3@MyDomain.com,johndoe2@MyDomain.com,johndoe1@MyDomain.com -Subject $messagesubject -Body $messagebody

                }

            }
        }
        else
        {
        $logfilemessage = $content.messagesdelivered.count.tostring() + " known-bad messages delivered."
        update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage
        }
    }
    catch
        {
        handle-errors
        }
    # We put the sleep command outside the main try-catch block so that if there's an error we don't throttle PP's API with calls to it.

    $logfilemessage = "Waiting 5mins..."
    update-logfile -logfile $targetlogfile -eventtype info -message $logfilemessage

    start-sleep -seconds 300
    }

until (2 -lt 1)



Take Ownership, Set-ACL and Propagation - Windows 7 Profile.v2

$
0
0

OK, so..

Windows 7 profiles are generated by AD by virtue that the Profile field is populated.

UNC is \\Server\Share\%username%\Profile\Profile.v2

Domain Admins can access up to \\Server\Share\%username%\Profile but not Profile.v2 folder. Age old known problem.

I need to take ownership of the folder, set-acl and propagate permissions. How can I achieve that in PS?

I've followed these and amalgamated some code, but I'm not very experienced and it doesn't work properly.

https://learn-powershell.net/2014/06/24/changing-ownership-of-file-or-folder-using-powershell/

https://social.technet.microsoft.com/Forums/office/en-US/87679d43-04d5-4894-b35b-f37a6f5558cb/solved-how-to-take-ownership-and-change-permissions-for-blocked-files-and-folders-in-powershell?forum=winserverpowershell

http://www.mcbsys.com/blog/2010/10/reset-roaming-profile-and-folder-redirection-permissions/

I have however successfully done this using a bat/cmd using takeown.exe and icacls.exe - but it's dog slow and I have to manually input the source folder.

Essentially I want to use an array (see my only other post) and pipe the sAMAccountName and then set permissions as mentioned.

Help?

Generating IIS Machine Keys with PowerShell

$
0
0

Hi - I have written a PowerShell script to update machine keys for a suite of web applications. I've used the "Generate-MachineKey" function found here: 

https://support.microsoft.com/en-us/kb/2915218#AppendixA

When I generate an HMACSHA512 validation key with this function I get a 256 character output string. But if I use Microsoft IIS admin utility to generate the same key I get a 128 character output string. 

I also notice both the IIS gui and the PowerShell function generate a 128 character output string for HMACSHA256 (so in PowerShell the output for HMACSHA512 is twice the length of HMACSHA256 but in IIS gui both are 128). 

I tested my apps with the PowerShell generated keys and everything works fine. But can anyone explain to me why the output is different lengths from different MS tools and not matching up with the lengths they say these values should be? I want to make sure this PowerShell function is good before I deploy these keys to production web apps. I have spent hours searching and can find no info about this. Any insight would be much appreciated. 

According to this article the lengths should be as stated below: 

https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.100).aspx

  • HMACSHA256 requires a 256-bit key (64 hexadecimal characters).

  • HMACSHA384 requires a 384-bit key (96 hexadecimal characters).

  • HMACSHA512 requires a 512-bit key (128 hexadecimal characters).


Unable to get InvokeSet ADSI code to work to update TS attributes

$
0
0

I have this code that I was using that used to work and as far as I know, nothing changed.  I've tried changing code around and absolutely can't get this to work.  QADUser isn't a viable option for me as I can't get the framework to install on my machine for some reason.

$userDN = Get-ADObject -LDAPFilter("samaccountname=tstuser") -Properties DistinguishedName
$userString = "LDAP://" + $userDN
        $user = [ADSI] "$userString"
        $user.psbase.invokeSet("TerminalServicesHomeDrive", "K:")
        $user.psbase.invokeSet("TerminalServicesHomeDirectory", "\\server\share")
        $user.setinfo()

results in:

Exception calling "InvokeSet" with "2" argument(s): "Unknown error (0x80005000)"
At <redacted>\test.ps1:4 char:9+         $user.psbase.invokeSet("TerminalServicesHomeDrive", "K:")+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException+ FullyQualifiedErrorId : DotNetMethodException

Exception calling "InvokeSet" with "2" argument(s): "Unknown error (0x80005000)"
At <redacted>\test.ps1:5 char:9+         $user.psbase.invokeSet("TerminalServicesHomeDirectory", "\\server\share" ...+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException+ FullyQualifiedErrorId : DotNetMethodException


Already running a command

$
0
0

On occasion when using a command that connects to a server, the command never completes.  If I try to cancel, I get the message "Already running a command.  Please Wait"  The wait would apparently be forever, or at least well beyond the capacity of my patience.  I usually either open a new tab, or close and reopen the ISE.

The command may be something like get-service or some GWMI query.  The server is online, but I may or may not have admin access to the server.  I guess it's possible the remote server may trying to respond, and PWS is waiting patiently for the reply.  I'm running the ISE Windows 7 enterprise.  In general the servers do NOT have WinRm enabled. 

Anyone have the same issue or an idea what the problem may be?  This doesn't happen that often but when I cancel a command I'd like my commands canceled. :)

Cmd-Let preference when is available from 2 different Modules

$
0
0

Is first time I have this scenario, I have the same CmdLets with same name from different modules and obviously with different parameters (one mandatory).

How can I force to use one in particular on my script? 

Any advice where to look for at PS doc? I don't know how to search this case.


PS C:\Windows\system32> Get-Command -Noun CATem*

CommandType     Name                                               ModuleName                                            
-----------     ----                                               ----------                                            
Function        Add-CATemplate                                     PSPKI                                                 
Function        Get-CATemplate                                     PSPKI                                                 
Function        Remove-CATemplate                               PSPKI                                                 
Function        Set-CATemplate                                     PSPKI                                                 
Cmdlet          Add-CATemplate                                     ADCSAdministration                                    
Cmdlet          Get-CATemplate                                     ADCSAdministration                                    
Cmdlet          Remove-CATemplate                               ADCSAdministration                                    


-- cesaru77--

passing arg to functions

$
0
0

I have a working function that I can pass an argument too.   Here is the top of my function:

Function Remove-Software {

    param(
    [parameter(ValueFromPipeline=$true)]
    [string[]]$Remove,
    [string[]]$Computer

    )
I can then pass the Remove argument to my function.  My issue is when my "remove" contains a space.  example "Adobe Reader"  Once it sees the space it fails.   How can I pass an argument to a function when it contains a space? 


mqh7

How to check the installed version of WMF on windwos 7

$
0
0
How can I check which version of WMF is installed on my machine?

Shared Mailboxes being deleted

$
0
0

Help!!!!

The below code when run on our Exchange 2016 Server - appears to delete most of our shared mailboxes.

Any ideas why?

. 'C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto

[CmdletBinding(SupportsShouldProcess=$True)]

# replace with your email address
$email    = "xxxxxxxxxxxxxxxxx"

# only need to populate these if you're impersonating...
$username = "xxxxxxx"
$password = "xxxxxxxxxxxxx"
$domain   = "xxxxxxxxx"

# load the assembly
#[void] [Reflection.Assembly]::LoadFile("C:\Progs\EwsManagedApi\Microsoft.Exchange.WebServices.dll")

# set ref to exchange, first references 2007, 2nd is 2010 (default)
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
#$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService

# use first option if you want to impersonate, otherwise, grab your own credentials
$s.Credentials = New-Object Net.NetworkCredential($username, $password, $domain)
#$s.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
#$s.UseDefaultCredentials = $true

# discover the url from your email address
$s.AutodiscoverUrl($email)

# get a handle to the inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#create a property set (to let us access the body & other details not available from the FindItems call)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;

$items = $inbox.FindItems(100)

foreach ($item in $items.Items)
{# we have an email
# load the property set to allow us to get to the body
$item.load($psPropertySet)
# colour our output
If ($item.IsRead)   # Only unread items
{}
Else
{
foreach ($eAdd in $item.ToRecipients)
{
#format our body
#replace any whitespace with a single space then get the 1st 100 chars
$bod = $item.Body.Text -replace '\s+', ' '
$bodCutOff = (100,$bod.Length | Measure-Object -Minimum).Minimum
$bod = $bod.Substring(0,$bodCutOff)
$bod = "$bod..."
$to_list = $eAdd.name
$send_to_list = ""
    
# we now have an email so find out who we need to email (if anyone)
[CmdletBinding(SupportsShouldProcess=$True)]
    
$dl = get-distributiongroup
# see if the send to is the owner of a group
foreach ($group in $dl) 
{
# get the owner eof the group
$gOwner = $group.ManagedBy.Name.ToString()
$dlgm = get-distributiongroupmember $group.name.ToString()
# is this the group that we want
if ($gOwner.equals($eAdd.Name) )
{
$send_to_list = ""
               foreach ($Member in $dlgm)
{
$this_address = $Member.PrimarySMTPAddress
$outlook = New-Object -comObject  Outlook.Application
$mail = $outlook.CreateItem(0)
write-output "To:-",$this_address
$mail.To = $this_address
$mail.Subject= "A New Email Has Arrived"
$mail.Body = "Please login and retrieve your email from " + $item.from 
#$mail.send()
send-mailmessage -from xxxxxxxxxxxxxxx  -to $this_address -body $mail.body -Subject $mail.Subject #-SMTPServer xxxxxxxxxxxx
}
}
}
}
$item.Isread = $True
$item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite) 
}
}


Alan Friend

Viewing all 21975 articles
Browse latest View live


Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>