Powershell script to check subfolders exist or not - powershell

I'm trying to write a script in PowerShell. There will be the main folder like eg: movies. Inside I will have a subfolder of which language of movie it is and another subfolder inside it for the movie name. I will be giving only the main folder path ie: F:\Movies, And I will be taking the language of the movie folder and movie name folder as parameters I want to verify if the folder is available inside the main folder or not. I wrote the below script but it's not working. Could you please help me to figure it out?
Function Folder_Check {
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true)]$Languageofmovie,
[Parameter(Mandatory=$true)]$nameofmovie)
$Foldertocheck = 'F:\Movies'
if ($result = Get-childitem -path $Foldertocheck -Recurse -Directory) {
Write-Host "Folder found in $($result)"
}
else {
Write-Host "No it is not available"
}
}

You can fix this by leveraging the parameters passed to the function.
Since you know the folder structure you can create a variable that combines the root folder, the language and the movie name:
Function Folder_Check {
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true)]$Languageofmovie,
[Parameter(Mandatory=$true)]$nameofmovie)
$Foldertocheck = '~\Documents\Movies'
$MovieFolder = "$Foldertocheck\$Languageofmovie\$nameofmovie"
if (Test-Path $MovieFolder -PathType Container) {
Write-Host "$MovieFolder found"
}
else {
Write-Host "$MovieFolder is not available"
}
}
Using -PathType Container to make sure the movie name is a folder and not a file.
Then you can call the function - something like:
Folder_Check English Godfather
Folder_Check English Armageddon
Folder_Check Russian TheIdiot

Did I understand correctly?
Function Folder_Check {
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true)]$Languageofmovie,
[Parameter(Mandatory=$true)]$nameofmovie)
$Foldertocheck = $Foldertocheck = 'F:\Movies' + '$($Languageofthemovie)'
if ((Get-childitem -path $Foldertocheck -Directory).name -match '$($nameofmovie)') {
Write-Host "Folder found in $($Foldertocheck)"
}
else {
Write-Host "No it is not available"
}
}

Related

Powershell - OpenFileDialog.FileName and FileBrowserDialog.SelectedFolder return an object instead of a string

I am trying to build a Powershell script to convert some audio files in a folder, and I am using a FolderBrowserDialog to ask the user the location of the output folder, and an OpenFileDialog to get the path of the converter program (in case it is not in the same folder of the script).
Both dialogs are called withing separate functions, which are called by the main program.
The problem is that when I return 'OpenFileDialog.FileName' and 'FolderBrowserDialog.SelectedPath' from each function, I get an object which contains the path and some other values and not the path itself as a string.
This are the objects I get from the functions:
OpenFileDialog.FileName Result
FolderBrowserdialog.SelectedPath Result
The functions are:
Function GetConverterPath
{
$currentDirectory = Split-Path -Parent $PSCommandPath;
$isConverterInCurrentDirectory = Test-Path $($currentDirectory + "\tfa2wav.exe")
if($isConverterInCurrentDirectory)
{
return ($currentDirectory + "\tfa2wav.exe");
}
[System.Windows.MessageBox]::Show("The converter's *.exe file was not found in the same directory as this script`n" +
"Please, point to the right file in the next dialog...", 'Converter not found...','Ok','Information');
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog;
$OpenFileDialog.filter = 'Executable files (*.exe)|*.exe';
$result = $OpenFileDialog.ShowDialog()
if($result -eq 'OK')
{
return $OpenFileDialog.FileName;
}
else
{
exit;
}
}
Function AskForOutputFolder
{
[System.Windows.MessageBox]::Show("In the next dialog you should select the folder where the converted sound files will be placed",
'Information','Ok','Information');
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|Out-Null;
$folderBrowserDialog = New-Object System.Windows.Forms.FolderBrowserDialog;
$folderBrowserDialog.Description = "Select a folder";
$result = $folderBrowserDialog.ShowDialog()
if($result -eq 'OK')
{
return $folderBrowserDialog.SelectedPath;
}
else
{
exit;
}
}
Any ideas on how to solve this?
Also, how can I prevent the 'OK' messages from appearing in the console after each dialog?
From Get-Help 'about_return':
In PowerShell, the results of each statement are returned as
output, even without a statement that contains the Return keyword.
Use e.g [System.Void] struct as follows
[void][System.Windows.MessageBox]::Show(…);
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');
As an alternative:
$null = [System.Windows.MessageBox]::Show(…);
Another alternative (slowest so avoid using this in loops):
[System.Windows.MessageBox]::Show(…) | Out-Null

How to get multiple Module configs auomatically to different folder using PowerShell?

I have Multiple folders, for Example, www contains Folders A, B, C and So on and this same structure exist in a different environment like INT, REG, DR, PROD. each contains different web.config.
So Here comes the challenge we need to provide an automated way to check-in each web.config.
Named like web_A_int.config, web_A_REG.config , Web_A_Prod.config, Web_A_DR.config and Web_B_int.config , Web_B_Reg_config and so on .
The environment is TFS (2015) Source Control and solution is .net based solution.
Please let me know if anything you might need to understand the question.
How to maintain this structure post build compilation. or How we can use proj or Powershell script to achieve it?
Desired Output:
INT--> www--> A, B,C Folders and each web.config placed inside respective folder.
REG--> www--> A, B, C --> with each web.config and each module level placed correctly.
One way to solve this is to use web transforms and create a web.{environment}.config file and then apply that transformation on deployment.
The Microsoft docs should get you started on how to use web transforms. I can provide you with some Powershell code on how to do this if that's how you decide to go.
I'm not familiar web server deployment in TFS, but here are some regular powershell functions you could use to build loops:
$environmentTypes = #('INT', 'REG', 'DR', 'PROD')
Function Get-WebConfig([String]$Path)
{
try {
$configContent = Get-Content \\path\to\config\file
}
catch {
Write-Debug "ERROR: Could not get content of $($Path)"
}
return $configContent
}
Function Create-FolderStructure() {
[cmdletBinding()]
param(
[Parameter(Mandatory)]
[ValidateSet('INT','REG','DR','PROD')]
[String]$EnvironmentType,
[Parameter(Mandatory)]
[String]$Server,
[Parameter(Mandatory)]
[String[]]$FolderNames,
[Parameter(Mandatory=$false)]
[Switch]$CheckServerUp
)
Begin {}
Process {
try {
if($CheckServerUp)
{
try {
Test-Connection -ComputerName $Server
}
catch {
Write-Debug "ERROR: Unable to test connection to $Server"
}
}
foreach($item in $FolderNames)
{
try {
New-Item -Path "\\$Server\c$\www\$item" -ItemType Directory
}
catch {
Write-Debug "ERROR: Unable to create folder $item"
}
try {
switch($EnvironmentType)
{
'INT'
{
$neededConfig = Get-WebConfig -Path \\path\to\your\intconfig
break
}
'REG'
{
$neededConfig = Get-WebConfig -Path \\path\to\your\regconfig
break
}
'DR'
{
$neededConfig = Get-WebConfig -Path \\path\to\your\drconfig
break
}
'PROD'
{
$neededConfig = Get-WebConfig -Path \\path\to\your\prodconfig
break
}
try {
New-Item -Path "\\$Server\c$\www\$item\Web_$EnvironmentType.config"
Set-Content -Path "\\$Server\c$\www\$item\Web_$EnvironmentType.config" -Value $neededConfig
}
catch {
Write-Debug "ERROR: Unable to create file"
}
}
}
catch {
Write-Debug "ERROR: Unable to get web config content"
}
}
}
catch {
Write-Debug "ERROR: Could not get content of $($Path)"
}
}
End{}
}

How to create nested Solution Folders with envdte

I've tried to create a visual studio solution with nested solution folders through Powershell (envdte). Everything works up to 1 level deep, but nesting a solution folder doesn't seem to work (interface is null). The issue is described in this SO question:
Creating a tree of Solution Folders using DTE and Package Manager Console
Unfortunately that question hasn't been answered yet. I've reachted out to the poster of that question but he had taken another route within his solution so the question is still open.
An excerpt of my code. The Find-Solution method finds the solutionfolder I'm looking for within the given context (= startfolder). When found, it returns this item:
function Find-SolutionFolder {
Param($SearchedFolderName, $StartFolder)
Write-Output "number " $StartFolder.ProjectItems.Count
For ($i = 1; $i -le $StartFolder.ProjectItems.Count; $i++) {
$Item = $StartFolder.ProjectItems.Item($i)
if ($Null -Eq $Item.Object) {
continue;
}
if ($Item.Object.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder) {
if ($Item.Name -Eq $SearchedFolderName) {
return $Item
}
Find-SolutionFolder $SearchedFolderName $Item
}
}
}
The Add-Projects method takes care of saving the structure to the solution. The structure is:
Solution
ModuleTypeFolder (ie. Foundation)
ModuleGroupFolder (optional)
Folder for project
projectfiles
This is a nested structure. Everything works without the ModuleGroupFolder but when the structure has the ModuleGroupFolder it causes the error due to the null result of the Get-Interface. I've confirmed that the correct solution folder is found. It's just the variable $moduleGroupNameFolderInterface is null.
The parameter modulePath is the path on disk
function Add-Projects {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[string]$ModulePath
)
Write-Output "Adding project(s)..."
# For the sake of the example always use a folder named 'Foundation'
$moduleTypeFolder = Get-FoundationSolutionFolder
# When the literal 'Foundation' solution folder does not exist in the solution it will be created.
if (-Not $moduleTypeFolder) {
$dte.Solution.AddSolutionFolder($config.ModuleType)
$moduleTypeFolder = Get-ModuleTypeSolutionFolder
}
$moduleTypeFolderInterface = Get-Interface $moduleTypeFolder.Object ([EnvDTE80.SolutionFolder])
# Add ModuleGroup Folder if needed
if (-Not [string]::IsNullOrWhiteSpace($config.ModuleGroupName)) {
$moduleGroupNameFolder = Find-SolutionFolder $config.ModuleGroupName $moduleTypeFolder
if (-Not $moduleGroupNameFolder) {
$moduleTypeFolderInterface.AddSolutionFolder($config.ModuleGroupName)
$moduleGroupNameFolder = Find-SolutionFolder $config.ModuleGroupName $moduleTypeFolder
}
$moduleGroupNameFolderInterface = Get-Interface $moduleGroupNameFolder.Object ([EnvDTE80.SolutionFolder])
if ($Null -eq $moduleGroupNameFolderInterface) {
Write-Output "moduleGroupNameFolderInterface is null; this is wrong"
} else {
$moduleNameFolder = $moduleGroupNameFolderInterface.AddSolutionFolder($config.ModuleName)
$moduleNameFolderInterface = Get-Interface $moduleNameFolder.SubProject ([EnvDTE80.SolutionFolder])
# Search in the new module folder for csproj files and add those to the solution.
Get-ChildItem -File -Path $ModulePath -Filter "*$csprojExtension" -Recurse | ForEach-Object { $moduleNameFolderInterface.AddFromFile("$($_.FullName)")}
}
} else {
$moduleNameFolder = $moduleTypeFolderInterface.AddSolutionFolder($config.ModuleName)
$moduleNameFolderInterface = Get-Interface $moduleNameFolder.Object ([EnvDTE80.SolutionFolder])
# Search in the new module folder for csproj files and add those to the solution.
Get-ChildItem -File -Path $ModulePath -Filter "*$csprojExtension" -Recurse | ForEach-Object { $moduleNameFolderInterface.AddFromFile("$($_.FullName)")}
}
Write-Output "Saving solution..."
$dte.Solution.SaveAs($dte.Solution.FullName)
}
Note. the example is not optimized (ie. duplicate code)
Can anybody help me solve the issue.
Update - answer to question
I finally figured it out. Apparently when finding a nested solution folder where property Kind has guid {66A26722-8FB5-11D2-AA7E-00C04F688DDE} it's not the correct object yet. You have to use the object within the found item.
So basically you are looking for recursion. You can recurse like this.
For the solutions folder:
function RecurseSolutionFolderProjects(){
param($solutionFolder = $(throw "Please specify a solutionFolder"))
$projectList = #()
for($i = 1; $i -le $solutionFolder.ProjectItems.Count; $i++){
$subProject = $solutionFolder.ProjectItems.Item($i).subProject
if($subProject -eq $null){
continue;
}
if($subProject.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder)
{
$projectList += RecurseSolutionFolderProjects($subProject)
} else {
$projectList += $subProject
}
}
return $projectList
}
For Project Files:
function GetProjectFiles(){
param($project = $(throw "Please specify a project"))
write-debug ("getting project files for " + $project.Name + " "+ $project.ProjectName)
$projectItems = RecurseDescendants($project.ProjectItems)
return $projectItems | Where-Object {$_.Kind -ne [EnvDTE.Constants]::vsProjectItemKindPhysicalFolder}
}
For Project Items:
function GetProjectItems(){
param($project = $(throw "Please specify a project"))
if($project.ProjectItems.count -gt 0){
write-debug "getting project items for '$project.Name' '$project.ProjectName'"
}
#example: GetProjectItems((GetSolutionProjects).get_Item(1))
$result =RecurseDescendants($project.ProjectItems)
return $result
}
Refer the Solution Hierarchy answer where the above functions are neatly explained
You can get the latest version from this GitHub Link
Hope it helps.

Powershell: Checking if Network Drive exists, if not, map it then double check

I am trying to write a simple script to check if a network drive is available, map it if it isn't, then double check the mapping worked (to report any issues like the account mapping it has accidentally expired etc). If it fails at the double check, it will send an email, otherwise it reports all ok.
I cannot get the double check to work. I think I have my statements wrong?
$Networkpath = "X:\Testfolder"
$pathExists = Test-Path -Path $Networkpath
If (-not ($pathExists)) {
(new-object -com WScript.Network).MapNetworkDrive("X:","\\Server-01\Share")
}
ELSEIF (-not ($pathExists)) {
Write-Host "Something went very wrong"
#Insert email code here
}
ELSE {Write-Host "Drive Exists already"}
I like James' answer but want to explain why you're having this issue. The reason your double check is failing is that you actually only check for the Path a single time.
In the beginning of the code, you check to see if the path exists on these two lines
$Networkpath = "X:\Testfolder"
$pathExists = Test-Path -Path $Networkpath
The variable $pathExists is created at this point and stores the outcome from that point in time. That's why your double check if failing later in the code, it's actually using the same output from the first time.
The code continues to test if the path exists, and if not, then creates the path.
If (-not ($pathExists)) {
(new-object -com WScript.Network).MapNetworkDrive("X:","\\Server-01\Share")
}
What you should do is add one more test here, then you'll know the drive already exists.
I added the extra test for you and slightly tweaked the flow through the script, with a Write-Host output for each branch. Here's the completed code.
$Networkpath = "X:\Testfolder"
$pathExists = Test-Path -Path $Networkpath
If ($pathExists) {
Write-host "Path already existed"
Return #end the function if path was already there
}
else {
(new-object -com WScript.Network).MapNetworkDrive("X:","\\Server-01\Share")
}
#Path wasn't there, so we created it, now testing that it worked
$pathExists = Test-Path -Path $Networkpath
If (-not ($pathExists)) {
Write-Host "We tried to create the path but it still isn't there"
#Insert email code here
}
ELSE {Write-Host "Path created successfully"}
You can use an if within an if (nested if) to perform a check after the drive has been mapped.
I also changed the logic of the first check so it doesn't use -not as it makes the code simpler.
$Networkpath = "X:\Testfolder"
If (Test-Path -Path $Networkpath) {
Write-Host "Drive Exists already"
}
Else {
#map network drive
(New-Object -ComObject WScript.Network).MapNetworkDrive("X:","\\Server-01\Share")
#check mapping again
If (Test-Path -Path $Networkpath) {
Write-Host "Drive has been mapped"
}
Else {
Write-Host "Something went very wrong"
}
}

How do I check if a file is present in a particular location?

I would just like help writing my if statement, I am having a hard time finding information online to do what I would like. Basically I need my if statement to see if the $file is located at a specified location (which can be multiple locations if possible). So far I have this:
foreach ($file in $MyInvocation.MyCommand.Path) {
if ($file) { #I need this to search a specific directory or directories
}
}
If you want to see if something exists try using the test-path command. This will return a true/false value that you can plug into subsequent if statements and do what you want respectively.
$fileTest = test-path [file path here]
if($fileTest -eq $true){
#what happens when the file exists
}
else{
#what happens when the file does not exist
}
You could also use a .NET method:
if(![System.IO.File]::Exists($file)){
# File exists
}
A better way to check if a path exists or not in PowerShell
If you just want to know if the file exists at one of the locations then use:
if( ( (test-path 'c:\testpath1\test.txt','c:\testpath2\test.txt') -eq $true).Count)
{
"File found!";
}
If you want to know where the file is found then execute the test-path for each path seperatly.
if( ( (test-path 'c:\testpath1\test.txt') -eq $true).Count)
{
"File found at testpath1!";
}
if( ( (test-path 'c:\testpath2\test.txt') -eq $true).Count)
{
"File found at testpath2!";
}