Using powershell reflection to perform database updates - c#

I'm editing my question to make it more readily understood.
Here is an example solution: https://github.com/mckenn55/PowershellTest
I created a brand new net47 MVC project. I added an area called "Database" and a controller within that area called "Update". Within that controller, I have the following:
public ActionResult Index()
{
return View(Execute());
}
public static List<string> Execute()
{
var returnable = new List<string>();
var assembly = Assembly.GetExecutingAssembly();
string codeBase = assembly.CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
var assemblyLocation = Path.GetDirectoryName(path);
string resourcePath = "";
string ModuleName = assembly.ManifestModule.Name;
ModuleName = ModuleName.Substring(0, ModuleName.LastIndexOf("."));
ModuleName = ModuleName.Replace(' ', '_').Replace(".", "");
string FolderPath = "Areas.Database.SQL";
FolderPath = FolderPath.Replace(' ', '_');
if (FolderPath != null && FolderPath.Length > 0 && FolderPath[FolderPath.Length - 1] == '.')
FolderPath = FolderPath.Substring(0, FolderPath.Length - 1);
StringBuilder filepath = new StringBuilder();
filepath.Append(ModuleName);
if (FolderPath != null && FolderPath.Length > 0)
{
filepath.Append('.' + FolderPath);
filepath.Append('.');
}
resourcePath = filepath.ToString();
string[] resourceNames = assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
{
if (Regex.Match(resourceName, "^" + resourcePath).Success)
{
returnable.Add(resourceName);
}
}
var orderedFileNames = new List<string>();
if (returnable != null && returnable.Any())
{
orderedFileNames = returnable.OrderBy(q => q).ToList();
}
else
{
returnable.Add("No files found");
}
return returnable;
}
Within the Database area, I have a directory called "SQL" and within that directory, I have a single file, TestFile.sql, included in the solution as an embedded resource. The results of the Execute() method, when viewed using the index action is "PSTest.Areas.Database.SQL.TestFile.sql". I would like to see the same thing in Powershell. I have tried the following:
> Add-Type -path "C:\Temp\PSTest\PSTest\bin\PSTest.dll"
> [PSTest.Areas.Database.UpdateController]::Execute()
No Files Found
Is my goal possible through powershell and if so, how?

I was not able to find a solution to this using powershell alone. I wrote a C# console app that is able to perform these actions without any issue.

Related

How to get files seperately to their extensions in MVC?

I wrote a function that when user clicks on button for pdf, user will only show the pdf documents. I'm having a difficulty about where to put returns in this function.
public IActionResult GetFiles(string dir) {
if ((dir == null) || (!Directory.Exists(dir))) { return BadRequest(); }
var filesList = new List<FileImage>();
var pdffilesList = new List<FileImage>();
var dirInfo = new DirectoryInfo(dir);
var files = dirInfo.GetFiles();
foreach (var file in files)
{
if (file.Extension.Contains(".pdf"))
{
pdffilesList.Add(new FileImage
{
Name = file.Name,
FullName = Regex.Match(file.FullName, "wwwroot(.*)").Groups[1].Value,
LastWriteTime = file.LastWriteTime.ToString("yyyy.MM.dd HH:mm"),
DirectoryName = file.DirectoryName,
Length = file.Length,
Extension = file.Extension
});
return Ok(pdffilesList);
}
else
{
filesList.Add(new FileImage
{
Name = file.Name,
FullName = Regex.Match(file.FullName, "wwwroot(.*)").Groups[1].Value,
LastWriteTime = file.LastWriteTime.ToString("yyyy.MM.dd HH:mm"),
DirectoryName = file.DirectoryName,
Length = file.Length,
Extension = file.Extension
});
}
}
return Ok(pdffilesList);
}
What should I change in here ?
If you just want the PDF files, then don't do anything to include the others:
foreach (var file in files)
{
if (file.Extension.Contains(".pdf"))
{
pdffilesList.Add(new FileImage
{
Name = file.Name,
FullName = Regex.Match(file.FullName, "wwwroot(.*)").Groups[1].Value,
LastWriteTime = file.LastWriteTime.ToString("yyyy.MM.dd HH:mm"),
DirectoryName = file.DirectoryName,
Length = file.Length,
Extension = file.Extension
});
// note: removed this `return`
//return Ok(pdffilesList);
}
// It's not a .pdf, so ignore it
}
return Ok(pdffilesList);
You might also consider whether you really want Contains here. Do you want to include files with extensions like ".pdfqpz" or "foopdf"? Contains will give you any file whose extension contains the string "pdf" anywhere in it. You also will miss files that have extensions ".PDF" or ".pDf", etc. You probably want something like:
if (file.Extension.Equals(".pdf", StringComparison.InvariantCultureIgnoreCase))
DirectoryInfo.GetFiles and EnumeratFiles can be used with a pattern. Instead of using separate branches you can use separate patterns:
var pattern=onlyPdfs? "*.pdf":"*";
var regex=new Regex("wwwroot(.*)");
var files=dirInfo.EnumerateFiles(pattern)
.Select(fi=>new FileImage
{
Name = file.Name,
FullName = regex.Match(file.FullName).Groups[1].Value,
LastWriteTime = file.LastWriteTime.ToString("yyyy.MM.dd HH:mm"),
DirectoryName = file.DirectoryName,
Length = file.Length,
Extension = file.Extension
});
return Ok(pdffilesList);
GetFiles waits until it finds all files and returns them in an array. EnumerateFiles on the other hand produces an IEnumerable<FileInfo> which returns each file as soon as it's found

C# fail to create file in directory if has other file

Can someone help me, I just learning C# for about 2 month, I have this problem,
i'm building a class for filter data from temp file and create the result in new txt file inside directory, if directory is empty nor at the same date, it build perfectly, and if there another file at same date it should create with increase the last number at lastname.
My problem when I run code, it is not creating if the directory has files with the same dates, then the result should be something like this:
C:\result_2014051301.txt
C:\result_2014051401.txt
C:\result_2014051402.txt <-- Failed, it is not ..2014051401.txt
class Entity2
{
public Entity2()
{
string fileTemp = "DEFAULT.temp";
string indexD = Properties.Settings.Default.ChIndex2D;
string indexC = Properties.Settings.Default.ChIndex2C;
string indexS = Properties.Settings.Default.ChIndex2S;
string tempPath = AppDomain.CurrentDomain.BaseDirectory;
string targetPath = Properties.Settings.Default.ExtractALL_DIR;
string SourceFile = Path.Combine(tempPath, fileTemp);
string tempFileX = Path.GetTempFileName();
if (!System.IO.Directory.Exists(targetPath))
{
System.Windows.Forms.MessageBox.Show("Error missing .temp", "Message Box");
}
else
{
string ext = ".txt";
int sequence = 0;
DateTime dateFileName = DateTime.Today;
string discode = Properties.Settings.Default.ChannelID_2;
string filename = discode + "_" + dateFileName.ToString("yyyyMMdd");
string pathX = Properties.Settings.Default.ExtractALL_DIR + #"/Channel2";
if (!Directory.Exists(pathX))
{
Directory.CreateDirectory(pathX);
}
string[] files = Directory.GetFiles(pathX, filename + "*.txt", SearchOption.TopDirectoryOnly);
if (files.Length > 0)
{
Array.Sort(files);
string lastFilename = files[files.Length - 1];
sequence = Int32.Parse(lastFilename.Substring(0, lastFilename.Length - 4).Replace(pathX + filename, ""));
}
sequence++;
string newFileName = filename + sequence.ToString().PadLeft(2, '0') + ext;
string DestFile = Path.Combine(pathX, newFileName);
using (var ab = new StreamReader(SourceFile))
using (var cd = new StreamWriter(DestFile))
{
string lineX;
while ((lineX = ab.ReadLine()) != null)
{
if (lineX.LastIndexOf("100", 3) != -1 || lineX.LastIndexOf("MGR", 15) != -1 || lineX.LastIndexOf(indexC, 15) != -1)
{
lineX = lineX.Replace(indexD, "");
lineX = lineX.Replace("DEFAULT", discode);
if (lineX.LastIndexOf("800", 3) != -1)
{
lineX = lineX.Replace(indexS, "");
}
cd.WriteLine(lineX);
}
}
}
}
}
}
This piece is not functioning correctly:
Int32.Parse(lastFilename.Substring(0, lastFilename.Length - 4).Replace(pathX + filename, ""));
pathX + filename is C:\folderfile.txt not C:\folder\file.txt.
You either need to add the \ or call Path.Join.
That will cause the Parse operation to fail since it tries to consume the who string (minus the extension).

Get root directory of a folder +1

How can i get the root directory of a folder +1?
Example:
Input: C:\Level1\Level2\level3
output should be:
Level1
If input is Level1
output should be Level1
if input is C:\ output should be empty string
Is there is a .Net function handles this?
Directory.GetDirectoryRoot will always returns C:\
You can use the Path-class + Substring + Split to remove the root and get the top-folder.
// your directory:
string dir = #"C:\Level1\Level2\level3";
// C:\
string root = Path.GetPathRoot(dir);
// Level1\Level2\level3:
string pathWithoutRoot = dir.Substring(root.Length);
// Level1
string firstFolder = pathWithoutRoot.Split(Path.DirectorySeparatorChar).First();
Another way is using the DirectoryInfo class and it's Parent property:
DirectoryInfo directory = new DirectoryInfo(#"C:\Level1\Level2\level3");
string firstFolder = directory.Name;
while (directory.Parent != null && directory.Parent.Name != directory.Root.Name)
{
firstFolder = directory.Parent.Name;
directory = directory.Parent;
}
However, i would prefer the "lightweight" string methods.
string dir = #"C:\foo\bar\woah";
var dirSegments = dir.Split(new char[] { Path.DirectorySeparatorChar },
StringSplitOptions.RemoveEmptyEntries);
if (dirSegments.Length == 1)
{
return string.Empty;
}
else
{
return dirSegments[0] + Path.DirectorySeparatorChar + dirSegments[1];
}
You could loop up using the directory info class using the following structure by adding the code section below into a method
string path = "C:\Level1\Level2\level3";
DirectoryInfo d = new DirectoryInfo(path);
while (d.Parent.FullName != Path.GetPathRoot(path))
{
d = d.Parent;
}
return d.FullName;
You could use DirectoryInfo and a while loop.
DirectoryInfo info = new DirectoryInfo(path);
while (info.Parent != null && info.Parent.Parent != null)
info = info.Parent;
string result = info.FullName;
Not sure whether this is the correct way but you do:
string s = #"C:\Level1\Level2\Level3";
string foo = s.split(#"\")[1];
Not sure whether DirectoryInfo object can get this in a cleaner manner..
DirectoryInfo di = new DirectoryInfo(#"C:\Level1\Level2\Level3");
di.Root;
One possible solution, but may not be the best, is to find the position of #"\", and do some manual processing yourself. Below code is not fully tested, just snippet:
//var positions = inputString.IndexOfAny(new [] {'\'}); //Original one
//Updated, thanks to Snixtor's implementation
var positions = inputString.IndexOfAny(new [] {Path.DirectorySeparatorChar});
int n=positions.Length;
if(n>=1)
{
var pos = positions[1]; //The 2nd '\';
return inputString.SubString(0, pos);
}
return null;
Of course, this only works if we are sure we want chop substrings after the 2nd '\'.
A happy linq one liner:
string level1_2 = Directory.GetDirectoryRoot(path) + path.Split(Path.DirectorySeparatorChar).Skip(1).Take(1).DefaultIfEmpty("").First();
var di = new System.IO.DirectoryInfo(#"C:\a\b\c");
Func<DirectoryInfo, DirectoryInfo> root = null;
root = (info) => info.Parent.FullName.EndsWith("\\") ? info : root(info.Parent);
var rootName = root(di).Name; //#a
Why not just use System.IO.Path to retrieve the name?
MessageBox.Show(System.IO.Path.GetFileName(
System.IO.Path.GetDirectoryName(
System.IO.Path.GetDirectoryName(#"C:\Level1\Level2\Level3")
)
));
This returns Level 1.
MessageBox.Show(System.IO.Path.GetFileName(
System.IO.Path.GetDirectoryName(
System.IO.Path.GetDirectoryName(#"C:\")
)
));
This returns empty string.

Get target of shortcut folder

How do you get the directory target of a shortcut folder? I've search everywhere and only finds target of shortcut file.
I think you will need to use COM and add a reference to "Microsoft Shell Control And Automation", as described in this blog post:
Here's an example using the code provided there:
namespace Shortcut
{
using System;
using System.Diagnostics;
using System.IO;
using Shell32;
class Program
{
public static string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFilename);
string filenameOnly = System.IO.Path.GetFileName(shortcutFilename);
Shell shell = new Shell();
Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
return link.Path;
}
return string.Empty;
}
static void Main(string[] args)
{
const string path = #"C:\link to foobar.lnk";
Console.WriteLine(GetShortcutTargetFile(path));
}
}
}
In windows 10 it needs to be done like this, first add COM reference to "Microsoft Shell Control And Automation"
// new way for windows 10
string targetname;
string pathOnly = System.IO.Path.GetDirectoryName(LnkFileName);
string filenameOnly = System.IO.Path.GetFileName(LnkFileName);
Shell shell = new Shell();
Shell32.Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null) {
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
targetname = link.Target.Path; // <-- main difference
if (targetname.StartsWith("{")) { // it is prefixed with {54A35DE2-guid-for-program-files-x86-QZ32BP4}
int endguid = targetname.IndexOf("}");
if (endguid > 0) {
targetname = "C:\\program files (x86)" + targetname.Substring(endguid + 1);
}
}
If you don't want to use dependencies you can use https://blez.wordpress.com/2013/02/18/get-file-shortcuts-target-with-c/
But lnk format is undocumented, so do it only if you understand risks.
An even simpler way to get the linked path that I use is:
private static string LnkToFile(string fileLink)
{
string link = File.ReadAllText(fileLink);
int i1 = link.IndexOf("DATA\0");
if (i1 < 0)
return null;
i1 += 5;
int i2 = link.IndexOf("\0", i1);
if (i2 < 0)
return link.Substring(i1);
else
return link.Substring(i1, i2 - i1);
}
But it will of course break if the lnk-file format changes.
public static string GetLnkTarget(string lnkPath)
{
var shl = new Shell();
var dir = shl.NameSpace(Path.GetDirectoryName(lnkPath));
var itm = dir.Items().Item(Path.GetFileName(lnkPath));
var lnk = (ShellLinkObject)itm.GetLink;
if (!File.Exists(lnk.Path)){
return lnk.Path.Replace("Program Files (x86)", "Program Files");
}
else{
return lnk.Path;
}
}
if you want find your application path that has shortcut on desktop, an easy way that i use, is the following:
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\\")
this code return any exe path that is running,Regardless that who requested file
Thanks to Mohsen.Sharify's answer I got more neat piece of code:
var fileName = Process.GetCurrentProcess().MainModule.FileName;
var folderName = Path.Combine(fileName, ".."); //origin folder
All file shortcuts have a .lnk file extension you can check for. Using a string for example, you could use string.EndsWith(".lnk") as a filter.
All URL shortcuts have a .url file extension, so you will need to account for those as well if needed.

Request App_GlobalResources directory on Application_Start

Question what do you do for request in Application_Start global asax i want to replace my path to my App_GlobalResources directory but i tried using request and it didn't work am i missing an assembly reference is there another way of doing it.
Updated Code:
List<string> languages = new List<string>
foreach (var file in Directory.EnumerateFiles(HttpContext.Current.Request.MapPath("App_GlobalResources"), "*.resx"))
{
string resource = Path.GetFileNameWithoutExtension(file);
if (resource.Length > 9)
{
string filename = resource.Substring(resource.IndexOf(".") + 1, resource.Length - resource.IndexOf(".") - 1);
RegionInfo regionInfo = new RegionInfo(filename);
if (!string.IsNullOrEmpty(filename))
{
llanguages.Add(filename);
} // error here
}
}
HttpContext.Current.Application.Add("Cultures", languages.ToArray());
List<string> languages = new List<string>();
foreach (var file in Directory.EnumerateFiles("C:\\Users\\KIRK\\Documents\\Visual Studio 2010\\WebSites\\WebSite2\\App_GlobalResources", "*.resx"))
{
string resource = Path.GetFileNameWithoutExtension(file);
if (resource.Length > 9) {
string filename = resource.Substring(resource.IndexOf(".") + 1, resource.Length - resource.IndexOf(".") - 1);
RegionInfo regionInfo = new RegionInfo(filename);
if (!string.IsNullOrEmpty(filename))
{ languages.Add(filename);
}
}
}
HttpContext.Current.Application.Add("Cultures", languages.ToArray());

Categories