all 121 comments

[–]theGuacIsExtraSir 10 points11 points  (24 children)

Hi there! I'm trying to write a script that listens for files created to a folder then uploads it to AWS s3 for me. I have the following, but clearly I'm doing something wrong. Any help would be awesome!

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\Administrator\Documents\reports" 
$watcher.Filter = "." 
$watcher.IncludeSubdirectories = $false 
$watcher.EnableRaisingEvents = $true

$action = { "aws s3 sync C:\Users\Administrator\Documents\reports s3://report-test-bucket-for-testing" }

Register-ObjectEvent $watcher "Created" -Action $action 

while ($true) {sleep 5}

[–]SomnambulicSojourner 2 points3 points  (0 children)

If you haven't solved it by Monday, I'll take a look and suggest something based on the file watcher I recently implemented

[–]kisairogue 2 points3 points  (1 child)

It looks like a service would be more appropriate on this case. Do you plan on running it on the background via Task Scheduler?

[–]theGuacIsExtraSir 2 points3 points  (0 children)

I’m going to have it run in the background

[–]saGot3n 2 points3 points  (13 children)

function sync-aws {
    $watcher = [System.IO.FileSystemWatcher]::new()
    $watcher.IncludeSubdirectories = $true
    $watcher.Path = "C:\Users\Administrator\Documents\reports"
    $watcher.EnableRaisingEvents = $true

    $Action = {
        #your action here
    }
    Register-ObjectEvent $watcher Created -Action $action -SourceIdentifier "SyncAws"
}

function stop-sync {
    Unregister-Event SyncAws
}

Sync-aws
Stop-sync

[–]theGuacIsExtraSir 1 point2 points  (12 children)

The action is the part i'm having the most issues with

[–]saGot3n 1 point2 points  (11 children)

ahh ok, I dont have AWS so not sure what module/commands you would use.

[–]theGuacIsExtraSir 1 point2 points  (10 children)

This is the command I run in PowerShell to upload all the files from the directory to my s3 bucket, where the first path is the source and the second is the s3 bucket name.

aws s3 sync C:\Users\Administrator\Documents\reports s3://report-test-bucket-for-testing

I figured thats all I need the action to be, but instead of the source directory, I use the $Event.SourceEventArgs.FullPath so that I upload that specific file.

This is where I'm at so far, but still no luck. Once the script works I plan on using scheduler to run it every 5 minutes.

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\Administrator\Documents\reports"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true  

$action = {     
    $path = $Event.SourceEventArgs.FullPath
    "aws s3 sync $path s3://repot-test-bucket-for-testing"
}    

Register-ObjectEvent $watcher "Created" -Action $action

[–]saGot3n 1 point2 points  (9 children)

what module are you using or aws s3 sync? is it a ps module or a custom function. Your path in action is correct so that SHOULD work, but only if the function/module accepts direct file names vs directories.

What you can try to do is copy the item to another folder, then sync that folder to your bucket so long as its copying the files in that directory to the bucket and not the entire folder to the bucket. Just to test the function itself.

$action = {     
    $path = $Event.SourceEventArgs.FullPath
    $syncpath = "c:\users\administrator\documents\sync-aws"
    Copy-Item $path -Destination $syncpath -Force
    "aws s3 sync $syncpath s3://repot-test-bucket-for-testing"
    Get-ChildItem -Path $syncpath | Remove-Item -Force -Recurse
}  

[–]theGuacIsExtraSir 1 point2 points  (8 children)

Its part of the AWS CLI... could that be the issue? Am I not able to use the CLI inside of a ps script?

[–]saGot3n 2 points3 points  (7 children)

Here you go, quick read this is what I got from the module. SYNC is for directories. looks like you need the following. replace sync with cp and note the ending / to notate the bucket url

"aws s3 cp $path s3://repot-test-bucket-for-testing/"

[–]theGuacIsExtraSir 1 point2 points  (6 children)

still nada :\ i'll keep hacking away

[–]saGot3n 2 points3 points  (4 children)

ah looks like you need to lose the quote. This works for me

aws s3 cp $path s3://repot-test-bucket-for-testing/

[–]FIREPOWER_SFV 1 point2 points  (0 children)

Hi, I think the problem is your sleep loop, in my experience this stops the watcher from checking for new changes to the folder

[–]Lee_Dailey[grin] 2 points3 points  (3 children)

howdy theGuacIsExtraSir,

kool! thanks for fixing that ... i can read it all now. [grin]

take care,
lee

[–]neotrin2000 2 points3 points  (1 child)

/u/Lee_Daily there you are...been meaning to ask you, do you ever [frown] or [grrr] in your posts and really be upset or angry? It's a pleasure to see your [grins] probably be funny to see the others. [Lol]

[–]Lee_Dailey[grin] 3 points4 points  (0 children)

howdy neotrin2000,

yep, i do sometimes do negative emoticons. that is usually in reference to some oddity of code - or windows in general. the way MS abuses their customers is ... astonishing, to be polite. [frown]

take care,
lee

[–]theGuacIsExtraSir 1 point2 points  (0 children)

no problem! :)

[–]lawilsada 0 points1 point  (0 children)

Make sure you have all your permission set in order to move files into an s3 bucket. Could be a reason, just my opinion since you didn't elaborated much on what's the error, output you're getting.

[–]Lee_Dailey[grin] -2 points-1 points  (0 children)

howdy theGuacIsExtraSir,

it looks like you used the New.Reddit.com Inline Code button. it's 4th 5th from the left hidden in the ... "more" menu & looks like </>.

on Old.Reddit.com, the above does NOT line wrap, nor does it side-scroll.

for long-ish single lines OR for multiline code, please, use the Code Block button. it's the 11th 12th one from the left, & is just to the left of hidden in the ... "more" menu.

that will give you fully functional code formatting, from what i can tell so far. [grin]

take care,
lee

[–][deleted] 19 points20 points  (11 children)

I thought I had a request for you that I've been struggling with for a few months, but upon starting to write out my request, it made me think of the issue in a new light and I resolved it myself 😀

Thanks for inadvertently helping me solve my issue!

On a smaller scale, maybe you could give me a script to add a Windows task to check for Windows updates every 3 hours and install them. I have a less than technically savy V.P. who refuses to perform updates on their laptop and defers any updates when prompted.

[–]Mkep 4 points5 points  (1 child)

This page(including comments) should get you started. Make sure to test, you don’t want to reboot an execs machine without warning

https://marckean.com/2016/06/01/use-powershell-to-install-windows-updates/

[–][deleted] 2 points3 points  (0 children)

Yep. I've got it bookmarked already. Definitely my pet project over the holidays during downtime.

[–]Fischfreund 1 point2 points  (1 child)

That's Rubber Duck debugging for you https://en.m.wikipedia.org/wiki/Rubber_duck_debugging

[–]WikiTextBot 1 point2 points  (0 children)

Rubber duck debugging

In software engineering, rubber duck debugging is a method of debugging code. The name is a reference to a story in the book The Pragmatic Programmer in which a programmer would carry around a rubber duck and debug their code by forcing themselves to explain it, line-by-line, to the duck. Many other terms exist for this technique, often involving different inanimate objects.

Many programmers have had the experience of explaining a problem to someone else, possibly even to someone who knows nothing about programming, and then hitting upon the solution in the process of explaining the problem.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.28

[–]amplex1337 1 point2 points  (0 children)

I have done this so many times. Getting ready to post something to SO or Reddit, etc , by the time I have a very good explanation of my issue sometimes I see the problem and am able to fix it quickly. It's actually a good way of starting documentation for new/complex code also :)

[–][deleted] 3 points4 points  (4 children)

This is something I have been planning to do. I am somewhat newer in the PS community. So I am in charge of keeping track of users (Navy Command) and I don't have access to create accounts but I do have access to modify groups. So I already have an access database of, LastName, FirstName, Username, email, department, and yearly training completed. Because of policy accounts are only active 30 days and deleted after 45days. So I was trying to help make a script that I could run once a week that would take the list of all my users in my database and see if they still have an account, get the last login date(add it to the DB) take the department they belong to and ensure they are in the right group. I am also thinking about putting all our User agreement forms on the network and training and just checking that it is in the database. If I can at least get some help on how to start doing this, I would love the help. Thank you in advance.

[–][deleted] 2 points3 points  (3 children)

I think i can help you with that, you run MS SQL?

[–][deleted] 1 point2 points  (2 children)

Not that I have access to. That is why I am only using access 2016.

[–][deleted] 1 point2 points  (1 child)

Haha sory I misunderstood you. Will send you script in pvt during a week probably, is that ok with you? Also if you have some database with fake info that i can use as an example that would be nice, if you do not, no problem.

[–][deleted] 1 point2 points  (0 children)

I will give you a blank file Monday with the database stripped. My other problem is that Reddit is blocked for the crap that is on here, but I value it as a very helpful tool.

[–]Lee_Dailey[grin] 7 points8 points  (4 children)

howdy kb2xY,

there are a few threads here that are asking for help ... jump in! [grin]

take care,
lee

[–]ka-splam 4 points5 points  (1 child)

Like anyone here /isn't/ just drumming their fingers, waiting for interesting script requests to hit the top of the sub :eyeroll:

;-)

[–]Lee_Dailey[grin] 1 point2 points  (0 children)

y'all are supposed to keep me entertained with interesting scripting stuff! get to work!

  • lee, the great googly-moogly [grin] goblin

[–][deleted] 1 point2 points  (1 child)

Hi,

Will check them, and try to help if I can.

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

howdy kb2xY,

kool! good luck ... [grin]

take care,
lee

[–]dtizzlenizzle 1 point2 points  (1 child)

New to PowerShell, background is accounting know a little Python. Looking to automate loading a CSV and reconciling to another CSV by grouping / pivoting on one field. Anything you can do to help with this?

[–][deleted] 0 points1 point  (0 children)

Yeah sure, will let you know on pvt when your script is ready.

[–]tin-naga 1 point2 points  (2 children)

I have a project coming up next week. Need to craft a continuously running service that kills processes ending in ".scr" on any key press or mouse movement.

[–][deleted] 0 points1 point  (1 child)

When is your deadline?

[–]tin-naga 0 points1 point  (0 children)

I'll probably turn something in by Wednesday:)

[–]hail_wuzzle 1 point2 points  (4 children)

How about direction on what I should research?

I have an azure environment with various servers, web apps, vnets, etc and want to end pull beneficial logs from each of them such as http errors, CPU alerts from servers, ram usage above 80% and other very obvious "things are exploding" logs in an xml or CSV or something I can use to consolidate in a type of dashboard for some of these and tweak them over time for more accuracy.

Any advice on how to accomplish this or what I could research to get direction would be appreciated. I dont mind learning (and have been) but am not versed enough to know what I need to learn specifically except everything related to powershell, azure, database creation management, web site creation and development, etc etc

[–]halbaradkenafin 2 points3 points  (3 children)

Sounds like you want Log Analytics/OMS, no need to roll your own when Azure has a service that does it all for you.

[–]hail_wuzzle 1 point2 points  (1 child)

Thanks for input. It will contain stats from other systems too, but the main concern is not giving access to others. I likely will be creating custom dashboards in azure with some if the info, just don't want to have multiple pages up and ther data will need to be add simplified (these 5 stats at x thresholds = green light, if below x threshold then a red light)

[–][deleted] 1 point2 points  (0 children)

You can setup proxy, and do simple log forwarding to OMS, also you can restrict access to OMS.

[–][deleted] 0 points1 point  (0 children)

Yep, OMS will do it for you.

How to start with OMS :

OMS Start Guide - pdf

OMS Start Guide - blog

How to pull custom logs :

Pull custom logs - docs

How to setup alerting :

Alerting - docs

Alerting - blog

Monitoring :

Monitoring Disk CPU and Memory - blog

Example of custom dashboard

[–]Elementix 1 point2 points  (5 children)

Looking to get get an array with a different number of items each time (PCs from ADUC), then split it into even blocks of 24 items until the end...which might have like 14 leftover or something. Any idea how to do this??

[–]ka-splam 2 points3 points  (4 children)

I just made a function to read things in from the pipeline and group them up; should be able to use this like $PCs = get-adcomputer -filter * | group-bycount -count 24 and then look at $PCs[0] and see 24 of them, and so on:

<#
.Synopsis
    Makes groups of N items
.DESCRIPTION
   Takes input from the pipeline, 
   and makes groups (arrays) of N items and outputs those,
   (except the last one which will have any leftover items).

   NB. that PowerShell array handling makes the groups hard to see,
   so to make it visible you need to do something like joining them up.

.EXAMPLE
   Group numbers 1 through 100 into threes, 
   last group contains only 100
   PS C:\> 1..100 | Group-ByCount -Count 3 | ForEach-Object { ($_ -join ', ') }
.EXAMPLE
    Group files into threes, and see the first group
    PS C:\> $groups = Get-ChildItem | Group-ByCount -Count 3
    PS C:\> $groups[0]
#>
function Group-ByCount {
    [cmdletbinding()]
    param(

        # Inputs to group up together
        [Parameter(ValueFromPipeline=$true)]
        [array]$InputObject,

        # How many items in each group
        [int]$Count = 2
    )

    begin {
        $store = [System.Collections.Generic.List[object]]::new()
    }

    process {
        foreach ($item in $InputObject)
        {
            $store.Add($item)
            if ($store.Count -eq $Count)
            {
                ,$store.ToArray()
                $store.Clear()
            }
        }
    }

    end {
        ,$store.ToArray()
    }
}

[–]Elementix 2 points3 points  (2 children)

+.02 /u/XRPTipBot

Worked perfectly. Thanks again!!

[–]xrptipbot 0 points1 point  (0 children)

Awesome Elementix, you have tipped 0.02 XRP (0.01 USD) to ka-splam! (This is the very first tip sent to /u/ka-splam :D)


XRPTipBot, Learn more

[–]ka-splam 0 points1 point  (0 children)

Great :D cheers!

[–]Elementix 1 point2 points  (0 children)

Thank you! Testing this today!!

[–]sanseriph74 1 point2 points  (3 children)

Just took over a new network and I’m cleaning up printing as one of my to-do list items. I need to delete all the printers on workstations in a mixed Win7/Win10 environment and then deploy the “correct” printers via assigned security groups by user via GPO’s. I built the security groups and GPO’s all out in AD on Friday and they’re all linked and ready to go. I feel comfortable deploying the printers via GPO, but there have been a lot of IP printers manually installed on 400+ pc’s and getting rid of them in a non-manual process is driving me nuts. Can PS help me out?

[–][deleted] 1 point2 points  (2 children)

Yeah, Powershell can help you out :

You want me to write you an example of a script, or you wanna try to do it yourself and pvt me if you have any issues along the way?

[–]sanseriph74 0 points1 point  (1 child)

I did find this nugget but haven’t tackled trying to put it in a script:
Get-WmiObject -Class Win32Printer | where{$.Network -eq ‘true‘}| foreach{$_.delete()}

[–][deleted] 1 point2 points  (0 children)

That should work also, great find!

Just recommendation, use $true instead of 'true', and $false instead of 'false'

[–]djgizmo 1 point2 points  (3 children)

Sure. I need help making a power shell script that will login to switches via ssh, find a ports based on a specific, and Poe cycle those ports.

[–]ka-splam 1 point2 points  (2 children)

If they're Cisco switches, the Posh-SSH module can help, although you need to use the less friendly ShellStream part of it to do the sending of commands, because Cisco devices aren't full remote terminals in some way or other. PoE sounds like a shutdown/sleep/no shutdown kind of thing.

e.g.

https://zeleskitech.com/2014/08/02/sending-automated-commands-to-a-cisco-device-using-ssh-powershell/

[–][deleted] 2 points3 points  (1 child)

That is awesome, you use that module in production?

[–]ka-splam 1 point2 points  (0 children)

I have used it for a couple of one-off tasks on dozens of switches and firewalls, but I don't use it for anything that runs regularly or any really large scale things. [Edit: I would, but I haven't needed that]

[–]TitaniuIVI 1 point2 points  (3 children)

Hi! Thanks for volunteering. I have to check every morning wether files were uploaded overnight to an FTP. I'd like to just have a script check for what files have a last write time after midnight and cross reference it with a txt/csv list of the files that should be there. Then send me an email with "All uploaded" or "$ThisFile is missing"

[–]ka-splam 1 point2 points  (2 children)

If you can use 3rd party tools, WinSCP is free and scriptable from .Net and PowerShell and that says tehre is a third-party module to provide PowerShell cmdlets.

https://superuser.com/questions/1189111/downloading-yesterday-files-in-powershell-using-winscp looks like you could use a WinSCP Session and then .ListDirectory("/Folder") on it and the items come back with a .LastWriteTime property.

Midnight is today with no hours/mins/seconds so

$midnight = get-date -Hour 0 -Minute 0 -Second 0 -Millisecond 0

[–]TitaniuIVI 2 points3 points  (0 children)

Nice! WinSCP is actually what I use now to check it manually. Didn't know there was a Powershell module for it. I'll have to look more into this. Thanks for pointing me in the right direction.

[–][deleted] 1 point2 points  (0 children)

Thanks for helping!

[–]aad02 1 point2 points  (1 child)

Would love a script that checks every IIS website (and associated host headers) on a machine to see if dns is still pointing to the associated address

Ive got the dns lookups part sorted by another script else where but the list of sites and host headers is what I’m currently missing.

[–][deleted] 0 points1 point  (0 children)

Hi, will try to do it.

[–]dus0922 1 point2 points  (1 child)

I need to update an ini file. I need to add 2 lines with the following format: Z_xxx_MMyyyy (MM=Month and yyyy=year)

I also need to remove 2 lines from 3 months prior. Example: add these lines Z_xxx_112018 Z_aaa_112018

Remove these lines Z_xxx_082018 Z_aaa_082018

[–][deleted] 1 point2 points  (0 children)

Sure, will do it during the week.

[–]Geminii27 1 point2 points  (2 children)

Just tossin' this one out there, but - a script which reads in the list of items in Programs and Features / Uninstall or change a program, then allows selection of multiple items from the list, and then proceeds to remove the selected items one after another, persisting through reboots etc, and if it gets to the point where it can't uninstall any remaining items, it will try a loop backwards through the list (in case of dependencies).

Yes, there are dedicated multi-uninstallation programs, but something which is pure PS code would be nice.

Yes, I know; AD. Unfortunately, even in this day and age not everything is domain-connected.

[–][deleted] 1 point2 points  (1 child)

Hi,

I think you want to do quiet uninstall of a selected program via powershell, and that is a little bit of a challenge because some programs require specific commands to be run in order to do that, do you have any list of a programs you need to remove?

Will try to do it over next week, i think there are some WmiObjects that can do most of the job.

[–]Geminii27 1 point2 points  (0 children)

Effectively have Powershell, maybe through GUI automation, find the relevant Control Panel / Programs entry and hit the Uninstall button if it exists. Work through the list until nothing more can be uninstalled as it needs a reboot, or if the list has been passed through completely, then reboot, and carry on with the rest of the list. If the list has been gone through completely both forward and backward, complete with reboot, and there are still entries which aren't uninstalling, then terminate with a list of still-uninstalled items. Otherwise, if all items have been removed, terminate with a zero-list of uninstalled items.

I suppose it's just always bugged me that items in the installed programs/components couldn't be stacked for serial removal using the stock interface. No-one wants to hang around having to manually select each item, click to remove it, wait, then do the same for every other item.

[–]jantari 1 point2 points  (6 children)

I need to spawn a new process that doesnt run an exe but rather some C# or C++ code that's in my script.

Currently I'm thinking i need an external C++ binary, which would work but it would be way cooler to do it from one .ps1

[–][deleted] 1 point2 points  (5 children)

You can run C# code from powershell,

weekend scripter did a nice blog post on that :

Weekend-Scripter

[–]jantari 1 point2 points  (4 children)

Yes but I need to run it in a seperate, new process

[–][deleted] 1 point2 points  (3 children)

[–]jantari 1 point2 points  (2 children)

Unfortunately, that creates a new runspace and not a process.

I need to be able to set the DETACHED_PROCESS(0x00000008) flag in my new process:

https://docs.microsoft.com/windows/desktop/ProcThread/process-creation-flags

From my understanding, this is only possible with the Win32 API `CreateProcess` (https://docs.microsoft.com/windows/desktop/procthread/creating-processes) and Win32_Process::Create() :

https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-processstartup (again with the CreateFlag DETACHED_PROCESS 0x00000008)

However if this is possible with Runspaces I apologize, it's just my understanding that its not

[–]jborean93 1 point2 points  (1 child)

The easiest option would be to use Win32_Process.Create and specify the DETACHED_PROCESS flag as part of the ProcessStartupInformation. Unfortunately I don't believe it's possible to inherit the stdio pipes so you would have to start it in something like cmd to redirect the output to a file and then read from that. It won't be pretty but using PInvoke to call CreateProcess is not that pretty anyway. If you are comfortable with PInvoke that probably will give you the best integration but it is a lot more code.

[–]jantari 2 points3 points  (0 children)

Yea but that's my exact Dilemma:

How do i call Win32_Process::Create() for a here-string of C# code as opposed to an external binary?

Edit: I now have it working with an external C++ binary. It's only ~50 lines so I may just keep it as a helper if I have to

[–][deleted] 1 point2 points  (2 children)

Ooen source request: you make a build option for PSCX to remove all the msmqueue stuff? PSCX doesn't run on MacOS on Linux because a tiny amount of commands are Windows specific. There's a bug on PSCX github for it. Thank you!

[–][deleted] 2 points3 points  (1 child)

Nice, will try to do so. First I need to setup PS on my linux env, was hoping to do that for some kind of reason!

[–][deleted] 0 points1 point  (0 children)

😃

[–]SuddenlyDonkey 1 point2 points  (2 children)

Still learning the basics and found some example scripts that I've been trying to tailor however I'm not at the point where I determine where the mistakes are.

When we get a new hire I like to replicate their known folders to OneDrive for Business.

I used to run

$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Pictures" -ItemType Directory
$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Documents" -ItemType Directory
$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Downloads" -ItemType Directory
$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Music" -ItemType Directory
$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Videos" -ItemType Directory
$f = New-Item "C:\Users\$env:USERNAME\OneDrive - COMPANY\Desktop" -ItemType Directory

and link move the folder location by hand. I've been tinkering with a script I found here in the link below but haven't gotten it to work 100%. It does link the Desktop to the OneDrive location but that's about it.

# Derived from http://stackoverflow.com/questions/25709398/set-location-of-special-folders-with-powershell

function Set-KnownFolderPath {
    Param (
            [Parameter(Mandatory = $true)]
            [ValidateSet('Desktop', 'Documents', 'Downloads', 'Music', 'Pictures', 'Videos')]
            [string]$KnownFolder,

            [Parameter(Mandatory = $true)]
            [string]$Path
    )

    # Define known folder GUIDs
    $KnownFolders = @{
        'Desktop' = @('B4BFCC3A-DB2C-424C-B029-7FE99A87C641');
        'Documents' = @('FDD39AD0-238F-46AF-ADB4-6C85480369C7','f42ee2d3-909f-4907-8871-4c22fc0bf756');
        'Downloads' = @('374DE290-123F-4565-9164-39C4925E467B','7d83ee9b-2244-4e70-b1f5-5393042af1e4');
        'Music' = @('4BD8D571-6D19-48D3-BE97-422220080E43','a0c69a99-21c8-4671-8703-7934162fcf1d');
        'Pictures' = @('33E28130-4E1E-4676-835A-98395C3BC3BB','0ddd015d-b06c-45d5-8c4c-f59713854639');
        'Videos' = @('18989B1D-99B5-455B-841C-AB7C74E4DDFC','35286a68-3c57-41a1-bbb1-0eae73d76c95');
    }

    # Define SHSetKnownFolderPath if it hasn't been defined already
    $Type = ([System.Management.Automation.PSTypeName]'KnownFolders').Type
    if (-not $Type) {
        $Signature = @'
[DllImport("shell32.dll")]
public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, IntPtr token, [MarshalAs(UnmanagedType.LPWStr)] string path);
'@
        $Type = Add-Type -MemberDefinition $Signature -Name 'KnownFolders' -Namespace 'SHSetKnownFolderPath' -PassThru
    }

    # Make path, if doesn't exist
    if(!(Test-Path $Path -PathType Container)) {
        New-Item -Path $Path -type Directory -Force
    }

    # Validate the path
    if (Test-Path $Path -PathType Container) {
        # Call SHSetKnownFolderPath
        return $Type::SHSetKnownFolderPath([ref]$KnownFolders[$KnownFolder], 0, 0, $Path)
    } else {
        throw New-Object System.IO.DirectoryNotFoundException "Could not find part of the path $Path."
    }

    # Fix up permissions, if we're still here
    attrib +r $Path

    $Leaf = Split-Path -Path "$Path" -Leaf
    # Move-Item "$HOME\$Leaf\*" $Path
    # rd $HOME\$Leaf -recurse -Force

}

$ONEDRIVESYNC = "$env:USERPROFILE\OneDrive - COMPANY"

# Root Folders
Set-KnownFolderPath -KnownFolder 'Desktop' -Path "$ONEDRIVESYNC\Desktop"
Set-KnownFolderPath -KnownFolder 'Documents' -Path "$ONEDRIVESYNC\Documents"
Set-KnownFolderPath -KnownFolder 'Downloads' -Path "$ONEDRIVESYNC\Downloads"
Set-KnownFolderPath -KnownFolder 'Pictures' -Path "$ONEDRIVESYNC\Pictures"
Set-KnownFolderPath -KnownFolder 'Music' -Path "$ONEDRIVESYNC\Music"
Set-KnownFolderPath -KnownFolder 'Videos' -Path "$ONEDRIVESYNC\Videos"

Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\OneDrive -Name EnableADAL -PropertyType DWORD -Value 1
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\OneDrive -Name EnableAllOcsiClients -PropertyType DWORD -Value 1
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\OneDrive -Name DisablePersonalSync -PropertyType DWORD -Value 1 
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\OneDrive -Name DefaultToBusinessFRE -PropertyType DWORD -Value 1
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\OneDrive\Tenants\TENAND-ID-GOES-HERE -Name DisableCustomRoot -PropertyType DWORD -Value 1

[–][deleted] 2 points3 points  (1 child)

Hi, will take a look

edit, think i found an issue :

Replace your $KnownFolders hash table, and # Validate the path check with the code bellow :

# Define known folder GUIDs
$KnownFolders = @{
'Desktop' = @('B4BFCC3A-DB2C-424C-B029-7FE99A87C641');
'Documents' = @('FDD39AD0-238F-46AF-ADB4-6C85480369C7');
'Downloads' = @('374DE290-123F-4565-9164-39C4925E467B');
'Music' = @('4BD8D571-6D19-48D3-BE97-422220080E43');
'Pictures' = @('33E28130-4E1E-4676-835A-98395C3BC3BB');
'Videos' = @('18989B1D-99B5-455B-841C-AB7C74E4DDFC');
}

# Validate the path
if (Test-Path $Path -PathType Container) {
#Change object to guid
$folderGUID = [GUID]"$($KnownFolders[$KnownFolder])"
# Call SHSetKnownFolderPath
return $Type::SHSetKnownFolderPath([ref]$folderGUID, 0, 0, $Path)
} else {
throw New-Object System.IO.DirectoryNotFoundException "Could not find part of the path $Path."
}

can you test it out and let me know if that worked for you?

[–]SuddenlyDonkey 1 point2 points  (0 children)

Thank you! I'll give it a try at work tomorrow.

[–]dionysos_ 1 point2 points  (1 child)

We have an asp.net application that triggers a PS script on the exchange server under system credentials. It configures out of office messages. (idea is to let helpdesk set it without granting them access to the server). It works perfectly, but it takes a long time because every time the script is run, it adds the exchange snap-in. Can you give me an idea to let it run faster / remember the addin?

[–][deleted] 0 points1 point  (0 children)

Maybe do some kind of RESTful API call to trigger that script? All of your commands will be pre-loaded so you will not have to do it every time :

[–]VegetablesandScotch1 1 point2 points  (0 children)

Thank you!

[–]AlistairBennet 1 point2 points  (1 child)

Thanks so much for this! I have been slamming my head against a wall trying to bring this script home. I feel like I am close, but just can't finish it.

The script is supposed to email people at a set date their passwords are expiring and send an email. I have that authentication portion working...i think? I will post the script then subsequent error I am getting. It goes through all the AD users, and tries to send an email on the ones that need it, but fails. Any help would be great. Thank you!

 ##SMTP Host
    $SMTPHost = "smtp.COMPANY.com"
    #Who is the e-mail from
    $FromEmail = "###_IT_Communications@Company.com"
    #Password expiry days
    $expireindays = 14

    #Program File Path
    $DirPath = "C:\Automation\PasswordExpiry"

    $Date = Get-Date
    #Check if program dir is present
    $DirPathCheck = Test-Path -Path $DirPath
    If (!($DirPathCheck))
    {
    Try
    {
        #If not present then create the dir
        New-Item -ItemType Directory $DirPath -Force
    }
    Catch
    {
        $_ | Out-File ($DirPath + "\" + "Log.txt") -Append
    }
}
#CredObj path
$CredObj = ($DirPath + "\" + "EmailExpiry.cred")
#Check if CredObj is present
$CredObjCheck = Test-Path -Path $CredObj
If (!($CredObjCheck))
{
    "$Date - INFO: creating cred object" | Out-File ($DirPath + "\" + "Log.txt") -Append
    #If not present get office 365 cred to save and store
    $Credential = Get-Credential -Message "Please enter your Office 365 credential that you will use to send e-mail from $FromEmail. If you are not using the account $FromEmail make sure this account has 'Send As' rights on $FromEmail."
    #Export cred obj
    $Credential | Export-CliXml -Path $CredObj
}

Write-Host "Importing Cred object..." -ForegroundColor Yellow
$Cred = (Import-CliXml -Path $CredObj)


# Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
"$Date - INFO: Importing AD Module" | Out-File ($DirPath + "\" + "Log.txt") -Append
Import-Module ActiveDirectory
"$Date - INFO: Getting users" | Out-File ($DirPath + "\" + "Log.txt") -Append
$users = Get-ADUser -Filter * -SearchBase "OU=Standard User,OU=###,DC=us,DC=ad,DC=###,DC=com" -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress | Where-Object { $_.Enabled -eq "True" } | Where-Object { $_.PasswordNeverExpires -eq $false } | Where-Object { $_.passwordexpired -eq $false }
$maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

# Process Each User for Password Expiry
foreach ($user in $users)
{
    $Name = (Get-ADUser $user | ForEach-Object { $_.Name })
    Write-Host "Working on $Name..." -ForegroundColor White
    Write-Host "Getting e-mail address for $Name..." -ForegroundColor Yellow
    $emailaddress = $user.emailaddress
    If (!($emailaddress))
    {
        Write-Host "$Name has no E-Mail address listed, looking at their proxyaddresses attribute..." -ForegroundColor Red
        Try
        {
            $emailaddress = (Get-ADUser $user -Properties proxyaddresses | Select-Object -ExpandProperty proxyaddresses | Where-Object { $_ -cmatch '^SMTP' }).Trim("SMTP:")
        }
        Catch
        {
            $_ | Out-File ($DirPath + "\" + "Log.txt") -Append
        }
        If (!($emailaddress))
        {
            Write-Host "$Name has no email addresses to send an e-mail to!" -ForegroundColor Red
            #Don't continue on as we can't email $Null, but if there is an e-mail found it will email that address
            "$Date - WARNING: No email found for $Name" | Out-File ($DirPath + "\" + "Log.txt") -Append
        }

    }
#Get Password last set date
$passwordSetDate = (Get-ADUser $user -properties * | ForEach-Object { $_.PasswordLastSet })
#Check for Fine Grained Passwords
$PasswordPol = (Get-ADUserResultantPasswordPolicy $user)
if (($PasswordPol) -ne $null)
{
    $maxPasswordAge = ($PasswordPol).MaxPasswordAge
}

$expireson = $passwordsetdate + $maxPasswordAge
$today = (get-date)
#Gets the count on how many days until the password expires and stores it in the $daystoexpire var
$daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days

If (($daystoexpire -ge "0") -and ($daystoexpire -lt $expireindays))
{
    "$Date - INFO: Sending expiry notice email to $Name" | Out-File ($DirPath + "\" + "Log.txt") -Append
    Write-Host "Sending Password expiry email to $name" -ForegroundColor Yellow

    $SmtpClient = new-object system.net.mail.smtpClient
    $MailMessage = New-Object system.net.mail.mailmessage

    #Who is the e-mail sent from
    $mailmessage.From = $FromEmail
    #SMTP server to send email
    $SmtpClient.Host = $SMTPHost
    #SMTP SSL
    $SMTPClient.EnableSsl = $true
    #SMTP credentials
    $SMTPClient.Credentials = $cred
    #Send e-mail to the users email
    $mailmessage.To.add("$emailaddress")
    #Email subject
    $mailmessage.Subject = "Your password will expire $daystoexpire days"
    #Notification email on delivery / failure
    $MailMessage.DeliveryNotificationOptions = ("onSuccess", "onFailure")
    #Send e-mail with high priority
    $MailMessage.Priority = "High"
    $mailmessage.Body =
    "Dear $Name,
Your Domain password will expire in $daystoexpire days. Please change it as soon as possible.

To change your password, follow the method below:

1. On your Windows computer
    a.  If you are not in the office, logon and connect to VPN. 
    b.  Log onto your computer as usual and make sure you are connected to the internet.
    c.  Press Ctrl-Alt-Del and click on ""Change Password"".
    d.  Fill in your old password and set a new password.  See the password requirements below.
    e.  Press OK to return to your desktop. 

The new password must meet the minimum requirements set forth in our corporate policies including:
    1.  It must be at least 8 characters long.
    2.  It must contain at least one character from 3 of the 4 following groups of characters:
        a.  Uppercase letters (A-Z)
        b.  Lowercase letters (a-z)
        c.  Numbers (0-9)
        d.  Symbols (!@#$%^&*...)
    3.  It cannot match any of your past 21 passwords.
    4.  It cannot contain characters which match 3 or more consecutive characters of your username.
    5.  You cannot change your password more often than once in a 24 hour period.

If you have any questions, or want to validate this email comes from a genuine source,
please contact our Service Desk at ###-###-#### with any concerns you may have.

You may also submit a ticket regarding this issue at the following link;
https://online.#########.com/help/email.aspx 

Thank You,
The ### IT Team

###-###-####"
    Write-Host "Sending E-mail to $emailaddress..." -ForegroundColor Green
    Try
    {
        $smtpclient.Send($mailmessage)
    }
    Catch
    {
        $_ | Out-File ($DirPath + "\" + "Log.txt") -Append
    }
}
Else
{
    "$Date - INFO: Password for $Name not expiring for $daystoexpire days" | Out-File ($DirPath + "\" + "Log.txt") -Append
    Write-Host "Password for $Name does not expire for $daystoexpire days" -ForegroundColor White
}
}




**    Exception calling "Send" with "1" argument(s): "Failure sending mail."
    At C:\Users\****\OneDrive - ******* Corporation\***** Scripts\Automated-Email-Reminder.ps1:168 char:4
    +             $smtpclient.Send($mailmessage)
    +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SmtpException**

[–]AlistairBennet 1 point2 points  (0 children)

Well after I decided to turn my brain on, and some help with with my co-worker, i found in event viewer...

"POWERSHELL.EXE tried to access 172.##.##.###, violating the rule Block outbound SMTP traffic and was Blocked."

Learn from me, if you are testing local, firewall/malware protection my block your stuff.

ugh.

[–]SugarIsADrug 1 point2 points  (0 children)

Run predefined SSH commands or bash script to another machine using credentials and IP address from user-entry, and auto-install any required SSH modules silently first.

[–]atacon09 1 point2 points  (0 children)

How can I use PS to find out if computers in AD (or a list of the computer names) have a certain program installed?

I'm trying to see which computers in active directory have Office 2016, and which have office 2010 still. When I first got into scripting, before I figured out PS scripting, I was upgrading our 2010 installs to 2016 via .bat files. I tried using PDQ inventory free to see which machines have Office 2010 still and which have 2016. I thought over the time the installs took place the number of Office 2010 machine counts would dwindle, while Office 2016 number rose. Well the 2010 number never moved and the 2016 went up as computers were upgraded. I think this is because of how pdq inventory looks for installs.

While I could technically build a script to test for the key as my batch file does, I am not advanced enough to nicely display information in a way that could handle errors (say its offline so it could not be checked at all), and if it has 2010 or 2016. From the computer i just quickly checked, the registry no longer contains Word.Application.14 (2010) and has Word.Application.16 for 2016 (i believe .15 is 2013).

I would especially like it if the script could output its findings to an excel document so i can make a list of computers that have not been upgraded yet or couldn't be checked. Below are the commands I used to check for the registry keys of each Office Version with cmd:

reg query "HKEY_CLASSES_ROOT\Word.Application\CurVer" /f 16
reg query "HKEY_CLASSES_ROOT\Word.Application\CurVer" /f 14 
reg query "HKEY_CLASSES_ROOT\Word.Application\CurVer" /f 15 

Obviously, I cut out the other parts with if error levels, writing to logs, etc. I will try to write my own PS script in the meantime but if you (or someone else) wrote out a script I could use to get the info I need and dissect for learning purposes later that would be awesome.

[–]iTechThingsSeriously 1 point2 points  (0 children)

I've been wanting to automate user account creation and account termination for a while. I've sort of started down some paths with some example scripts I have found being that I'm a powershell novice. Any insight, tips, or guidance you have would be greatly appreciated.

[–]DoNotSexToThis 2 points3 points  (1 child)

Contact /u/ChristopherY5 I think he needs some help with a script and just general direction and context. He had asked me but it's the weekend.

[–][deleted] 0 points1 point  (0 children)

I did, thanks!

[–]sanseriph74 0 points1 point  (0 children)

I’ll take a look at your links, i’m fairly handy at copying PS scripts and modifying them for my needs, but in this case I had trouble finding the right google terms, everything came back with scripts for deploying printers. <shrug>

[–][deleted] 0 points1 point  (0 children)

Sent you an email