Powershell copy file with variable - variables

I'm trying to run the following script that I thought was quite simple. What am I doing wring here...
[Environment]::UserName = $username
Write-Host "The user is $username"
$from = "c:\Users\" + $username + "\favourites\*.*"
$to = "c:\test"
Write-Host "This is from dir: $from"
Write-Host "This is to dir: $to"
Copy-Item $from $to
The script does not seem to like the + $username + ...

I think you got your first line the wrong way around. Currently you're assigning an empty variable (value of it should be $null) to $Env:UserName, thus overwriting the username, not reading it.
I think it should be
$username = [Environment]::Username
or, as noted above, you can access environment variables via the special Env: drive:
$username = $Env:Username
And unrelated to your problem, just a matter of nicer code:
You can put the username directly into the string (which you seem to know, as demonstrated a line above – where you don't need a string in this case, though):
$from = "C:\Users\$username\favourites\*"
You don't need to fetch the user name at all, you can use
$Env:UserProfile
or
[Environment]::GetFolderPath([Environment+SpecialFolder]::UserProfile)
or even
[Environment]::GetFolderPath([Environment+SpecialFolder]::Favorites)
which might ultimately be what you're after, here.

Related

Powershell Help to compare

Hope you all are safe and well !!
I am running a script that gives me Azure AD apps with its secret end date property. The property name which gives me all details in Azure AD is “PasswordCredentials” and I am using get-azureadapplication cmdlet.
What is the best way to check If the app has end date value within a month and filter on it, I tried where-object with get-date.adddays(30) and tried to compare with -lt operators.
Appreciate your support here.
Well, in your case, you should note there may be several PasswordCredentials for one app, so you need to use a loop to check every PasswordCredential.
And the EndDate you got from the Get-AzureADApplication command is a UTC time, but Get-Date returns the local time, so you need to use (Get-Date).AddDays(30).ToUniversalTime() instead of (Get-Date).AddDays(30). Also, if you just want to check the expiring ones, you must exclude the ones that have expired, so use $PasswordCredential.EndDate -gt $nowdate like below.
As you did not give your script, I can just give a sample for you, my sample is for a single app, if you want to check all the apps in your tenant, use a loop to do that.
$PasswordCredentials = (Get-AzureADApplication -ObjectId <object-id>).PasswordCredentials
$nowdate = (Get-Date).ToUniversalTime()
$wantdate = (Get-Date).AddDays(30).ToUniversalTime()
foreach($PasswordCredential in $PasswordCredentials){
if($PasswordCredential.EndDate -lt $wantdate -and $PasswordCredential.EndDate -gt $nowdate){
$keyid = $PasswordCredential.KeyId
Write-Output "The key with KeyId $keyid will expire"
}
}
Update:
If you want to get the AppId and AppName, you could use the script below.
$apps = Get-AzureADApplication -All $true
$nowdate = (Get-Date).ToUniversalTime()
$wantdate = (Get-Date).AddDays(30).ToUniversalTime()
foreach($app in $apps){
$PasswordCredentials = $app.PasswordCredentials
$appid = $app.AppId
$displayname = $app.DisplayName
foreach($PasswordCredential in $PasswordCredentials){
if($PasswordCredential.EndDate -lt $wantdate -and $PasswordCredential.EndDate -gt $nowdate){
$a = $app | select #{Name="AppId"; Expression={$appid}}, #{Name="DisplayName"; Expression={$displayname}}, #{Name="EndDate"; Expression={$PasswordCredential.EndDate}}
Write-Output $a
}
}
}

VB.net and powershell variables

I have a Visual Studio form running with VB.net and I'm collecting info needed to setup an AD user. In the end, this info will need to simply be passed to Powershell with no return info needed. Before that though, I need it to check if a printer code has already been assigned to someone before allowing it to be submitted to another user. I have a simple powershell script written up for it.
(We use the Pager field to store the printer code.)
Import-Module ActiveDirectory
$Page = $args[0]
Get-ADUser -Filter { Pager -like $Page } | FT Name
I setup the code I found HERE, and attempted to modify it to my script but it keeps crashing on
Dim results As Collection(Of PSObject) = MyPipeline.Invoke()
It gives me: An unhandled exception of type 'System.Management.Automation.ParseException' occurred in System.Management.Automation.dll
If I run his little 6+5 basic example script, it works, but when I try to retrieve info and return a name, it doesn't like it. How can I get it to return the name of the person if it find it? And since it won't run, I'm not even sure if passing the printer code as $args[0] is going to work yet.
Your results is expecting a collection of PowerShell objects. When you pipe the Get-ADUser command to Format-Table, it effectively strips the object down to a stream of strings. Try without the | FT Name.
Import-Module ActiveDirectory #if you're using powershell 3 or later, this may be redundant
# $Page = $args[0] # don't need to do this
$results = Get-ADUser -Filter { Pager -like $args[0] }
Write-Verbose $results
#Write-Verbose $results.Name #try this if the above one works
Update:
Write-Verbose may be causing an issue.
Try this:
Get-ADUser -Filter { Pager -like $args[0] }
Just that one line as the total PS code. (Assuming you have PowerShell 3.0 or later, you don't need Import-Module) That line will return objects of type TypeName: Microsoft.ActiveDirectory.Management.ADUser (from `Get-ADUser username | Get-Member).
You may also be able to use the .Net object type directly, without PowerShell. I'm not knowledgeable about .NET beyond what I picked up working with PowerShell.
Accessing AD using .NET, info from MSDN.

Looping a powershell script

This might seem like an easy question but I had to ask. I have a powershell script that calls another script and it patches a SQL database. Normally you can just patch all databases at once, but sometimes that halts and you have to cancel it and do single datasbases instead. Here is the script I made to do this sqlps is already run prior to this code segment:
do {
$dabname = Read-Host "Enter the database name or (stop) to end"
if($dabname -ne "stop") {
$sclient = Read-Host "Enter Client name"
$date = Get-Date -Format "yymmdd"
$sqlsrvname = Read-Host "Please enter the sql server name"
SQL-remote -DBServer $sqlsrvname -DBNameList $dabname –client $sclient –mainline HTFS –datefolder $date –targetenv $sqlsrvname}
}until($dabname -eq "stop")
but it keeps telling me the server doesnt exist, I cant figure out what I did wrong can someone please tell me whats missing? This script its suppose to; once working; keep asking if you want to patch more databases after patching them until you say "stop." The sql-remote is a function in which the sql patch script is stored.

Cronjob does not execute command line in perl script

I am unfamiliar with linux/linux environment so do pardon me if I make any mistakes, do comment to clarify.
I have created a simple perl script. This script creates a sql file and as shown, it would execute the lines in the file to be inserted into the database.
#!/usr/bin/perl
use strict;
use warnings;
use POSIX 'strftime';
my $SQL_COMMAND;
my $HOST = "i";
my $USERNAME = "need";
my $PASSWORD = "help";
my $NOW_TIMESTAMP = strftime '%Y-%m-%d_%H-%M-%S', localtime;
open my $out_fh, '>>', "$NOW_TIMESTAMP.sql" or die 'Unable to create sql file';
printf {$out_fh} "INSERT INTO BOL_LOCK.test(name) VALUES ('wow');";
sub insert()
{
my $SQL_COMMAND = "mysql -u $USERNAME -p'$PASSWORD' ";
while( my $sql_file = glob '*.sql' )
{
my $status = system ( "$SQL_COMMAND < $sql_file" );
if ( $status == 0 )
{
print "pass";
}
else
{
print "fail";
}
}
}
insert();
This works if I execute it while I am logged in as a user(I do not have access to Admin). However, when I set a cronjob to run this file let's say at 10.08am by using the line(in crontab -e):
08 10 * * * perl /opt/lampp/htdocs/otpms/Data_Tsunami/scripts/test.pl > /dev/null 2>&1
I know the script is being executed as the sql file is created. However no new rows are inserted into the database after 10.08am. I've searched for solutions and some have suggested using the DBI module but it's not available on the server.
EDIT: Didn't manage to solve it in the end. A root/admin account was used to to execute the script so that "solved" the problem.
First things first, get rid of the > /dev/null 2>&1 at the end of your crontab entry (at least temporarily) so you can actually see any errors that may be occurring.
In other words, change it temporarily to something like:
08 10 * * * perl /opt/lampp/htdocs/otpms/Data_Tsunami/scripts/test.pl >/tmp/myfile 2>&1
Then you can examine the /tmp/myfile file to see what's being output.
The most likely case is that mysql is not actually on the path in your cron job, because cron itself gives a rather minimal environment.
To fix that problem (assuming that's what it is), see this answer, which gives some guidelines on how best to expand the cron environment to give you what you need. That will probably just involve adding the MySQL executable directory to your PATH variable.
The other thing you may want to consider is closing the out_fh file before trying to pass it to mysql - if the buffers haven't been flushed, it may still be an empty file as far as other processes are concerned.
The expression glob(".* *") matches all files in the current working
directory.
- http://perldoc.perl.org/functions/glob.html
you should not rely on the wd in a cron job. If you want to use a glob (or any file operation) with a relative path, set the wd with chdir first.
source: http://www.perlmonks.org/bare/?node_id=395387
So if your working directory is, for example /home/user, you should insert
chdir('/home/user/');
before the WHILE, ie:
sub insert()
{
my $SQL_COMMAND = "mysql -u $USERNAME -p'$PASSWORD' ";
chdir('/home/user/');
while( my $sql_file = glob '*.sql' )
{
...
replace /home/user with wherever your sql files are being created.
It's better to do as much processing within Perl as possible. It avoids the overhead of generating a separate shell process and leaves everything under the control of the program so that you can handle any errors much more simply
Database access from Perl is done using the DBI module. This program demonstrates how to achieve what you have written using the mysql utility. As you can see it's also much more concise
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $host = "i";
my $username = "need";
my $password = "help";
my $dbh = DBI->connect("DBI:mysql:database=test;host=$host", $username, $password);
my $insert = $dbh->prepare('INSERT INTO BOL_LOCK.test(name) VALUES (?)');
my $rv = $insert->execute('wow');
print $rv ? "pass\n" : "fail\n";

How to search with multiple keys in a hash table in powershell

I'm writing a Powershell script and in it I'm using a hash table to store information about database checks. The table has 5 keys (host, check, last execution time, last rep, status) and I want to search in my table for values where:
$s = $table where $host -eq $hostname -and check -eq $check
Does anyone have any idea how this is done? And if it makes any difference, the script cannot rely on .NET framework higher than 2.0
I´m new to Powershell and scripting in general so this might be very obvious but I still can't seem to find an answer on Google. Also if someone knows a good reference page for Powershell scripting I would really appreciate a link.
Gísli
EDIT: Don't see how it matters but here is a function I use to create a hash table:
function read_saved_state{
$state = #{}
$logpos = #{}
$last_log_rotate = 0
foreach($s in Get-Content $saved_state_file){
$x = $s.split('|')
if($x[0] -eq 'check'){
$state.host = $x[1]
$state.check = $x[2]
$state.lastexec = $x[3]
$state.lastrep = $x[4]
$state.status = $x[5]
}
elseif($x[0] -eq 'lastrotate'){
$last_log_rotate = $x[1]
}
elseif($x[0] -eq 'log'){
$logpos.lastpos = $x[3]
}
}
$saved_state_file has one line for each check run and can also have a line for last log rotate and last log position. There can be as many as 12 checks for one host.
I'm trying to extract a particular check, run at a particular host, and changing the lastexec_time, last_rep and status.
return $state,$logpos,$last_log_rotate
}
Assuming you have an array or list of hashtables (not entirely clear from the question), your syntax is pretty close:
$s = $tables | where {($_.host -eq $hostname) -and ($_.check -eq $check)}