mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
805 lines
24 KiB
C#
805 lines
24 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
|
||
namespace DataUtils
|
||
{
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Path
|
||
{
|
||
public string Current
|
||
{
|
||
get
|
||
{
|
||
try { return Directory.GetCurrentDirectory (); }
|
||
catch { return string.Empty; }
|
||
}
|
||
set
|
||
{
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty (value)) Directory.SetCurrentDirectory (value);
|
||
}
|
||
catch { /* ignore */ }
|
||
}
|
||
}
|
||
public string Program
|
||
{
|
||
get { return Utilities.GetCurrentProgramPath (); }
|
||
}
|
||
public string Root
|
||
{
|
||
get
|
||
{
|
||
try
|
||
{
|
||
string prog = Utilities.GetCurrentProgramPath ();
|
||
return Path.GetDirectoryName (prog) ?? string.Empty;
|
||
}
|
||
catch { return string.Empty; }
|
||
}
|
||
}
|
||
public string Combine (string l, string r)
|
||
{
|
||
if (string.IsNullOrEmpty (l)) return r ?? string.Empty;
|
||
if (string.IsNullOrEmpty (r)) return l ?? string.Empty;
|
||
try { return Path.Combine (l, r); }
|
||
catch { return l + Path.DirectorySeparatorChar + r; }
|
||
}
|
||
public string GetName (string path)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||
try
|
||
{
|
||
return Path.GetFileName (path);
|
||
}
|
||
catch { return string.Empty; }
|
||
}
|
||
public string GetDirectory (string path)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||
try
|
||
{
|
||
return Path.GetDirectoryName (path) ?? string.Empty;
|
||
}
|
||
catch { return string.Empty; }
|
||
}
|
||
public string GetDir (string path) { return GetDirectory (path); }
|
||
public bool Exist (string path)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return false;
|
||
return File.Exists (path) || Directory.Exists (path);
|
||
}
|
||
public bool FileExist (string filepath)
|
||
{
|
||
if (string.IsNullOrEmpty (filepath)) return false;
|
||
return File.Exists (filepath);
|
||
}
|
||
public bool DirectoryExist (string dirpath)
|
||
{
|
||
if (string.IsNullOrEmpty (dirpath)) return false;
|
||
return Directory.Exists (dirpath);
|
||
}
|
||
public bool DirExist (string dirpath) { return DirectoryExist (dirpath); }
|
||
public string GetEnvironmentString (string str)
|
||
{
|
||
if (string.IsNullOrEmpty (str)) return string.Empty;
|
||
try
|
||
{
|
||
return Environment.ExpandEnvironmentVariables (str);
|
||
}
|
||
catch { return str; }
|
||
}
|
||
// Valid Windows filename?
|
||
public bool ValidName (string filename)
|
||
{
|
||
if (string.IsNullOrEmpty (filename)) return false;
|
||
char [] invalid = Path.GetInvalidFileNameChars ();
|
||
return filename.IndexOfAny (invalid) < 0;
|
||
}
|
||
// filter may be e.g. "*.txt;*.md" or using "\" separators per legacy code
|
||
public string EnumFilesToJson (string dir, string filter, bool withpath, bool sort, bool includesub)
|
||
{
|
||
var arr = EnumFiles (dir, filter, withpath, sort, includesub);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string EnumDirsToJson (string dir, bool withpath, bool sort, bool includesub)
|
||
{
|
||
var arr = EnumDirs (dir, withpath, sort, includesub);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string EnumSubDirsToJson (string dir, bool withpath)
|
||
{
|
||
var arr = EnumSubDirs (dir, withpath);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string [] EnumFiles (string dir, string filter, bool withpath, bool sort, bool includesub)
|
||
{
|
||
if (string.IsNullOrEmpty (dir)) return new string [0];
|
||
var patterns = Utilities.SplitFilters (filter);
|
||
var list = new List<string> (100);
|
||
|
||
try
|
||
{
|
||
var searchOption = includesub ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||
foreach (var pat in patterns)
|
||
{
|
||
try
|
||
{
|
||
foreach (var f in Directory.EnumerateFiles (dir, pat, searchOption))
|
||
{
|
||
list.Add (withpath ? f : Path.GetFileName (f));
|
||
}
|
||
}
|
||
catch (UnauthorizedAccessException) { /* skip */ }
|
||
catch (DirectoryNotFoundException) { /* skip */ }
|
||
catch (IOException) { /* skip */ }
|
||
}
|
||
|
||
if (sort)
|
||
{
|
||
list.Sort (StringComparer.OrdinalIgnoreCase);
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// fallback: empty
|
||
}
|
||
|
||
return list.ToArray ();
|
||
}
|
||
public string [] EnumDirs (string dir, bool withpath, bool sort, bool includesub)
|
||
{
|
||
if (string.IsNullOrEmpty (dir)) return new string [0];
|
||
var list = new List<string> (100);
|
||
try
|
||
{
|
||
var searchOption = includesub ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||
foreach (var d in Directory.EnumerateDirectories (dir, "*", searchOption))
|
||
{
|
||
list.Add (withpath ? d : Path.GetFileName (d));
|
||
}
|
||
if (sort) list.Sort (StringComparer.OrdinalIgnoreCase);
|
||
}
|
||
catch { }
|
||
return list.ToArray ();
|
||
}
|
||
public string [] EnumSubDirs (string dir, bool withpath)
|
||
{
|
||
return EnumDirs (dir, withpath, true, true);
|
||
}
|
||
public string CommonPrefix (string path1, string path2)
|
||
{
|
||
if (string.IsNullOrEmpty (path1) || string.IsNullOrEmpty (path2)) return string.Empty;
|
||
try
|
||
{
|
||
string a = Utilities.NormalizeFullPath (path1);
|
||
string b = Utilities.NormalizeFullPath (path2);
|
||
string [] asplit = a.Split (new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||
string [] bsplit = b.Split (new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||
int min = Math.Min (asplit.Length, bsplit.Length);
|
||
var sb = new StringBuilder ();
|
||
for (int i = 0; i < min; i++)
|
||
{
|
||
if (!string.Equals (asplit [i], bsplit [i], StringComparison.OrdinalIgnoreCase)) break;
|
||
sb.Append (asplit [i]);
|
||
sb.Append (Path.DirectorySeparatorChar);
|
||
}
|
||
return sb.ToString ().TrimEnd (Path.DirectorySeparatorChar);
|
||
}
|
||
catch { return string.Empty; }
|
||
}
|
||
public string EnsureDirSlash (string dir)
|
||
{
|
||
if (string.IsNullOrEmpty (dir)) return string.Empty;
|
||
try
|
||
{
|
||
if (!dir.EndsWith (Path.DirectorySeparatorChar.ToString ()))
|
||
dir += Path.DirectorySeparatorChar;
|
||
return dir;
|
||
}
|
||
catch { return dir; }
|
||
}
|
||
public string Normalize (string path)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||
try { return Path.GetFullPath (path); }
|
||
catch { return path; }
|
||
}
|
||
public string FullPathName (string path) { return Normalize (path); }
|
||
public string FullPath (string path) { return FullPathName (path); }
|
||
public string Expand (string path) { return GetEnvironmentString (path); }
|
||
// GetFolder via SHGetFolderPath (preserves the original csidl param usage)
|
||
public string GetFolder (int csidl)
|
||
{
|
||
try
|
||
{
|
||
// try P/Invoke to SHGetFolderPath
|
||
return ShellHelpers.GetFolderPath (csidl);
|
||
}
|
||
catch
|
||
{
|
||
return string.Empty;
|
||
}
|
||
}
|
||
// KnownFolder by GUID string (wraps SHGetKnownFolderPath)
|
||
public string KnownFolder (string guidString)
|
||
{
|
||
if (string.IsNullOrWhiteSpace (guidString)) return string.Empty;
|
||
Guid guid;
|
||
try
|
||
{
|
||
guid = new Guid (guidString);
|
||
}
|
||
catch
|
||
{
|
||
return string.Empty;
|
||
}
|
||
|
||
try
|
||
{
|
||
return ShellHelpers.GetKnownFolderPath (guid);
|
||
}
|
||
catch
|
||
{
|
||
return string.Empty;
|
||
}
|
||
}
|
||
public bool PEquals (string l, string r)
|
||
{
|
||
if (l == null && r == null) return true;
|
||
if (l == null || r == null) return false;
|
||
string a = Utilities.NormalizeFullPath (l);
|
||
string b = Utilities.NormalizeFullPath (r);
|
||
return string.Equals (a, b, StringComparison.OrdinalIgnoreCase);
|
||
}
|
||
public bool Open (string path)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return false;
|
||
try
|
||
{
|
||
if (File.Exists (path))
|
||
{
|
||
Process.Start (path);
|
||
return true;
|
||
}
|
||
|
||
if (Directory.Exists (path))
|
||
{
|
||
Process.Start ("explorer.exe", path);
|
||
return true;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
// Basic entry object
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Entry
|
||
{
|
||
protected string path;
|
||
public _I_Entry (string path)
|
||
{
|
||
this.path = path ?? string.Empty;
|
||
}
|
||
public _I_Entry ()
|
||
{
|
||
this.path = string.Empty;
|
||
}
|
||
public virtual string Path
|
||
{
|
||
get { return path; }
|
||
set { path = value ?? string.Empty; }
|
||
}
|
||
public virtual string Name
|
||
{
|
||
get
|
||
{
|
||
try
|
||
{
|
||
return System.IO.Path.GetFileName (path) ?? string.Empty;
|
||
}
|
||
catch { return string.Empty; }
|
||
}
|
||
}
|
||
public virtual string Directory
|
||
{
|
||
get
|
||
{
|
||
try { return System.IO.Path.GetDirectoryName (path) ?? string.Empty; }
|
||
catch { return string.Empty; }
|
||
}
|
||
}
|
||
public virtual string Root { get { return Directory; } }
|
||
public virtual bool Exist
|
||
{
|
||
get
|
||
{
|
||
return File.Exists (path) || System.IO.Directory.Exists (path);
|
||
}
|
||
}
|
||
public virtual string Uri
|
||
{
|
||
get
|
||
{
|
||
try
|
||
{
|
||
Uri uri;
|
||
if (System.Uri.TryCreate (path, UriKind.Absolute, out uri))
|
||
{
|
||
return uri.AbsoluteUri;
|
||
}
|
||
else
|
||
{
|
||
Uri u = new Uri (System.IO.Path.GetFullPath (path));
|
||
return u.AbsoluteUri;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
return string.Empty;
|
||
}
|
||
}
|
||
}
|
||
public virtual string FullPath
|
||
{
|
||
get
|
||
{
|
||
try { return System.IO.Path.GetFullPath (path); }
|
||
catch { return path; }
|
||
}
|
||
}
|
||
|
||
// Return relative path from frontdir to this.Path; similar semantics to C++ code
|
||
public string RelativePath (string frontdir)
|
||
{
|
||
if (string.IsNullOrEmpty (path) || string.IsNullOrEmpty (frontdir)) return string.Empty;
|
||
try
|
||
{
|
||
string fullFile = System.IO.Path.GetFullPath (path);
|
||
string fullDir = System.IO.Path.GetFullPath (frontdir);
|
||
if (!fullDir.EndsWith (System.IO.Path.DirectorySeparatorChar.ToString ()))
|
||
fullDir += System.IO.Path.DirectorySeparatorChar;
|
||
|
||
if (!string.Equals (System.IO.Path.GetPathRoot (fullFile), System.IO.Path.GetPathRoot (fullDir), StringComparison.OrdinalIgnoreCase))
|
||
return string.Empty;
|
||
|
||
if (!fullFile.StartsWith (fullDir, StringComparison.OrdinalIgnoreCase)) return string.Empty;
|
||
|
||
return fullFile.Substring (fullDir.Length);
|
||
}
|
||
catch
|
||
{
|
||
return string.Empty;
|
||
}
|
||
}
|
||
}
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_File: _I_Entry
|
||
{
|
||
// last encoding used when reading
|
||
protected Encoding lastEncoding;
|
||
public _I_File () : base (string.Empty) { }
|
||
public _I_File (string filepath) : base (filepath) { }
|
||
// Read file contents; detect BOM if present by using StreamReader with detectEncodingFromByteOrderMarks = true
|
||
public string Get ()
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||
try
|
||
{
|
||
using (FileStream fs = new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||
using (StreamReader sr = new StreamReader (fs, Encoding.UTF8, true))
|
||
{
|
||
string text = sr.ReadToEnd ();
|
||
lastEncoding = sr.CurrentEncoding;
|
||
return text;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
public void Set (string content)
|
||
{
|
||
if (string.IsNullOrEmpty (path)) return;
|
||
try
|
||
{
|
||
string dir = System.IO.Path.GetDirectoryName (path);
|
||
if (!string.IsNullOrEmpty (dir) && !System.IO.Directory.Exists (dir))
|
||
{
|
||
System.IO.Directory.CreateDirectory (dir);
|
||
}
|
||
Encoding enc = lastEncoding ?? Encoding.UTF8;
|
||
using (FileStream fs = new FileStream (path, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||
using (StreamWriter sw = new StreamWriter (fs, enc))
|
||
{
|
||
sw.Write (content ?? string.Empty);
|
||
sw.Flush ();
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// ignore write errors
|
||
}
|
||
}
|
||
public string Content
|
||
{
|
||
get { return Get (); }
|
||
set { Set (value); }
|
||
}
|
||
public override bool Exist
|
||
{
|
||
get { return File.Exists (path); }
|
||
}
|
||
public string FilePath
|
||
{
|
||
get { return this.Path; }
|
||
set { this.Path = value; }
|
||
}
|
||
}
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Directory: _I_Entry
|
||
{
|
||
public _I_Directory () : base (string.Empty) { }
|
||
public _I_Directory (string dirpath) : base (dirpath) { }
|
||
public _I_Directory (_I_Entry file) : base (file != null ? file.Directory : string.Empty) { }
|
||
|
||
public string DirectoryPath
|
||
{
|
||
get { return this.Path; }
|
||
set { this.Path = value; }
|
||
}
|
||
public string DirPath { get { return DirectoryPath; } set { DirectoryPath = value; } }
|
||
public override bool Exist { get { return System.IO.Directory.Exists (path); } }
|
||
public string EnumFilesToJson (string filter, bool withpath, bool sort, bool includesub)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
string [] arr = p.EnumFiles (DirPath, filter, withpath, sort, includesub);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string EnumDirsToJson (bool withpath, bool sort, bool includesub)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
string [] arr = p.EnumDirs (DirPath, withpath, sort, includesub);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string EnumSubDirsToJson (bool withpath)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
string [] arr = p.EnumSubDirs (DirPath, withpath);
|
||
return Utilities.StringArrayToJson (arr);
|
||
}
|
||
public string [] EnumFiles (string filter, bool withpath, bool sort, bool includesub)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
return p.EnumFiles (DirPath, filter, withpath, sort, includesub);
|
||
}
|
||
public string [] EnumDirs (bool withpath, bool sort, bool includesub)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
return p.EnumDirs (DirPath, withpath, sort, includesub);
|
||
}
|
||
public string [] EnumSubDirs (bool withpath)
|
||
{
|
||
_I_Path p = new _I_Path ();
|
||
return p.EnumSubDirs (DirPath, withpath);
|
||
}
|
||
}
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Explorer
|
||
{
|
||
[DllImport ("user32.dll")]
|
||
private static extern IntPtr GetForegroundWindow ();
|
||
class WindowWrapper: IWin32Window
|
||
{
|
||
private IntPtr _hwnd;
|
||
public WindowWrapper (IntPtr handle) { _hwnd = handle; }
|
||
public IntPtr Handle { get { return _hwnd; } }
|
||
}
|
||
private static IWin32Window GetActiveWindowOwner ()
|
||
{
|
||
IntPtr hWnd = GetForegroundWindow ();
|
||
return hWnd != IntPtr.Zero ? new WindowWrapper (hWnd) : null;
|
||
}
|
||
private static void CallJS (object jsFunc, params object [] args)
|
||
{
|
||
if (jsFunc == null) return;
|
||
try
|
||
{
|
||
object [] realArgs = new object [args.Length + 1];
|
||
realArgs [0] = jsFunc; // thisArg
|
||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||
jsFunc.GetType ().InvokeMember (
|
||
"call",
|
||
System.Reflection.BindingFlags.InvokeMethod,
|
||
null,
|
||
jsFunc,
|
||
realArgs
|
||
);
|
||
}
|
||
catch { }
|
||
}
|
||
public void File (string filter, string initDir, object jsCallback)
|
||
{
|
||
IWin32Window owner = GetActiveWindowOwner ();
|
||
Thread t = new Thread (() => {
|
||
string result = string.Empty;
|
||
try
|
||
{
|
||
using (OpenFileDialog dlg = new OpenFileDialog ())
|
||
{
|
||
dlg.Filter = filter;
|
||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||
: initDir;
|
||
dlg.Multiselect = false;
|
||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||
result = dlg.FileName;
|
||
}
|
||
}
|
||
catch { }
|
||
CallJS (jsCallback, result);
|
||
});
|
||
t.IsBackground = true;
|
||
t.SetApartmentState (ApartmentState.STA);
|
||
t.Start ();
|
||
}
|
||
public void Files (string filter, string initDir, object jsCallback)
|
||
{
|
||
IWin32Window owner = GetActiveWindowOwner ();
|
||
Thread t = new Thread (() => {
|
||
string result = "[]";
|
||
try
|
||
{
|
||
using (OpenFileDialog dlg = new OpenFileDialog ())
|
||
{
|
||
dlg.Filter = filter;
|
||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||
: initDir;
|
||
dlg.Multiselect = true;
|
||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||
result = Newtonsoft.Json.JsonConvert.SerializeObject (dlg.FileNames);
|
||
}
|
||
}
|
||
catch { }
|
||
CallJS (jsCallback, result);
|
||
});
|
||
t.IsBackground = true;
|
||
t.SetApartmentState (ApartmentState.STA);
|
||
t.Start ();
|
||
}
|
||
public void Dir (string initDir, object jsCallback)
|
||
{
|
||
IWin32Window owner = GetActiveWindowOwner ();
|
||
Thread t = new Thread (() => {
|
||
string result = string.Empty;
|
||
try
|
||
{
|
||
using (FolderBrowserDialog dlg = new FolderBrowserDialog ())
|
||
{
|
||
dlg.SelectedPath = string.IsNullOrEmpty (initDir)
|
||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||
: initDir;
|
||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||
result = dlg.SelectedPath;
|
||
}
|
||
}
|
||
catch { }
|
||
|
||
CallJS (jsCallback, result);
|
||
});
|
||
t.IsBackground = true;
|
||
t.SetApartmentState (ApartmentState.STA);
|
||
t.Start ();
|
||
}
|
||
public void Dirs (string initDir, object jsCallback)
|
||
{
|
||
IWin32Window owner = GetActiveWindowOwner ();
|
||
Thread t = new Thread (() => {
|
||
string result = "[]";
|
||
try
|
||
{
|
||
using (var dlg = new OpenFileDialog ())
|
||
{
|
||
// trick: 多选文件夹
|
||
dlg.ValidateNames = false;
|
||
dlg.CheckFileExists = false;
|
||
dlg.CheckPathExists = true;
|
||
dlg.FileName = "SelectFolder";
|
||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||
: initDir;
|
||
dlg.Multiselect = true;
|
||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||
{
|
||
var dirs = dlg.FileNames.Select (f => Path.GetDirectoryName (f)).Distinct ().ToArray ();
|
||
result = Newtonsoft.Json.JsonConvert.SerializeObject (dirs);
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
CallJS (jsCallback, result);
|
||
});
|
||
t.IsBackground = true;
|
||
t.SetApartmentState (ApartmentState.STA);
|
||
t.Start ();
|
||
}
|
||
}
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Folder
|
||
{
|
||
[DllImport ("shell32.dll")]
|
||
private static extern int SHGetKnownFolderPath (
|
||
[MarshalAs (UnmanagedType.LPStruct)] Guid rfid,
|
||
uint dwFlags,
|
||
IntPtr hToken,
|
||
out IntPtr ppszPath);
|
||
private static string KF (Guid g)
|
||
{
|
||
IntPtr p;
|
||
SHGetKnownFolderPath (g, 0, IntPtr.Zero, out p);
|
||
string s = Marshal.PtrToStringUni (p);
|
||
Marshal.FreeCoTaskMem (p);
|
||
return s;
|
||
}
|
||
private static readonly Guid FOLDERID_Downloads = new Guid ("374DE290-123F-4565-9164-39C4925E467B");
|
||
private static readonly Guid FOLDERID_SavedPictures = new Guid ("3B193882-D3AD-4EAB-965A-69829D1FB59F");
|
||
private static readonly Guid FOLDERID_SavedGames = new Guid ("4C5C32FF-BB9D-43B0-BF90-45A0FEEB6D0E");
|
||
private static readonly Guid FOLDERID_Links = new Guid ("BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968");
|
||
private static readonly Guid FOLDERID_Contacts = new Guid ("56784854-C6CB-462B-8169-88E350ACB882");
|
||
private static readonly Guid FOLDERID_Searches = new Guid ("7D1D3A04-DEBB-4115-95CF-2F29DA2920DA");
|
||
public string ProgramFiles => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFiles);
|
||
public string ProgramFilesX86 => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86);
|
||
public string Windows => Environment.GetFolderPath (Environment.SpecialFolder.Windows);
|
||
public string System32 => Environment.SystemDirectory;
|
||
public string UserProfile => Environment.GetFolderPath (Environment.SpecialFolder.UserProfile);
|
||
public string Desktop => Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
|
||
public string Documents => Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
|
||
public string Pictures => Environment.GetFolderPath (Environment.SpecialFolder.MyPictures);
|
||
public string Music => Environment.GetFolderPath (Environment.SpecialFolder.MyMusic);
|
||
public string Videos => Environment.GetFolderPath (Environment.SpecialFolder.MyVideos);
|
||
public string AppDataRoaming => Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
|
||
public string AppDataLocal => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
|
||
public string AppDataLocalLow => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData) + "\\Low";
|
||
public string Temp => System.IO.Path.GetTempPath ();
|
||
public string PublicDesktop => Environment.GetFolderPath (Environment.SpecialFolder.CommonDesktopDirectory);
|
||
public string PublicDocuments => Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments);
|
||
public string PublicPictures => Environment.GetFolderPath (Environment.SpecialFolder.CommonPictures);
|
||
public string PublicMusic => Environment.GetFolderPath (Environment.SpecialFolder.CommonMusic);
|
||
public string PublicVideos => Environment.GetFolderPath (Environment.SpecialFolder.CommonVideos);
|
||
public string Downloads => KF (FOLDERID_Downloads);
|
||
public string SavedPictures => KF (FOLDERID_SavedPictures);
|
||
public string SavedGames => KF (FOLDERID_SavedGames);
|
||
public string Links => KF (FOLDERID_Links);
|
||
public string Contacts => KF (FOLDERID_Contacts);
|
||
public string Searches => KF (FOLDERID_Searches);
|
||
}
|
||
[ComVisible (true)]
|
||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||
public class _I_Storage
|
||
{
|
||
[DllImport ("user32.dll")]
|
||
private static extern IntPtr GetForegroundWindow ();
|
||
class WindowWrapper: IWin32Window
|
||
{
|
||
private IntPtr _hwnd;
|
||
public WindowWrapper (IntPtr handle) { _hwnd = handle; }
|
||
public IntPtr Handle { get { return _hwnd; } }
|
||
}
|
||
private static IWin32Window GetActiveWindowOwner ()
|
||
{
|
||
IntPtr hWnd = GetForegroundWindow ();
|
||
return hWnd != IntPtr.Zero ? new WindowWrapper (hWnd) : null;
|
||
}
|
||
private static void CallJS (object jsFunc, params object [] args)
|
||
{
|
||
if (jsFunc == null) return;
|
||
try
|
||
{
|
||
// 这里固定第一个参数为 thisArg(比如 1)
|
||
object [] realArgs = new object [args.Length + 1];
|
||
realArgs [0] = jsFunc; // thisArg
|
||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||
|
||
jsFunc.GetType ().InvokeMember (
|
||
"call",
|
||
BindingFlags.InvokeMethod,
|
||
null,
|
||
jsFunc,
|
||
realArgs
|
||
);
|
||
}
|
||
catch
|
||
{
|
||
// ignore errors in callback invocation
|
||
}
|
||
}
|
||
protected _I_Path path = new _I_Path ();
|
||
public _I_Path Path { get { return path; } }
|
||
public _I_File GetFile (string path) { return new _I_File (path); }
|
||
public _I_Directory GetDirectory (string path) { return new _I_Directory (path); }
|
||
public _I_Directory GetDir (string path) { return GetDirectory (path); }
|
||
public _I_Explorer Explorer => new _I_Explorer ();
|
||
public void Save (string filter, string initDir, string defaultName, object jsCallback)
|
||
{
|
||
IWin32Window owner = GetActiveWindowOwner ();
|
||
Thread t = new Thread (() => {
|
||
string result = string.Empty;
|
||
try
|
||
{
|
||
using (SaveFileDialog dlg = new SaveFileDialog ())
|
||
{
|
||
dlg.Filter = filter;
|
||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||
: initDir;
|
||
if (!string.IsNullOrEmpty (defaultName))
|
||
dlg.FileName = defaultName;
|
||
dlg.OverwritePrompt = true;
|
||
dlg.AddExtension = true;
|
||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||
result = dlg.FileName;
|
||
}
|
||
}
|
||
catch { }
|
||
CallJS (jsCallback, result);
|
||
});
|
||
t.IsBackground = true;
|
||
t.SetApartmentState (ApartmentState.STA);
|
||
t.Start ();
|
||
}
|
||
public _I_Folder Folders => new _I_Folder ();
|
||
}
|
||
// Small shell helpers that P/Invoke for folder retrieval using CSIDL or Known Folder GUIDs
|
||
internal static class ShellHelpers
|
||
{
|
||
[System.Runtime.InteropServices.DllImport ("shell32.dll")]
|
||
private static extern int SHGetFolderPathW (IntPtr hwndOwner, int nFolder, IntPtr hToken, uint dwFlags, [System.Runtime.InteropServices.MarshalAs (System.Runtime.InteropServices.UnmanagedType.LPWStr)] StringBuilder pszPath);
|
||
public static string GetFolderPath (int csidl)
|
||
{
|
||
StringBuilder sb = new StringBuilder (260);
|
||
int hr = SHGetFolderPathW (IntPtr.Zero, csidl, IntPtr.Zero, 0, sb);
|
||
if (hr == 0) return sb.ToString ();
|
||
return string.Empty;
|
||
}
|
||
[System.Runtime.InteropServices.DllImport ("shell32.dll")]
|
||
private static extern int SHGetKnownFolderPath ([System.Runtime.InteropServices.MarshalAs (System.Runtime.InteropServices.UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
|
||
[System.Runtime.InteropServices.DllImport ("ole32.dll")]
|
||
private static extern void CoTaskMemFree (IntPtr pv);
|
||
public static string GetKnownFolderPath (Guid guid)
|
||
{
|
||
IntPtr pathPtr;
|
||
int hr = SHGetKnownFolderPath (guid, 0, IntPtr.Zero, out pathPtr);
|
||
if (hr != 0 || pathPtr == IntPtr.Zero) return string.Empty;
|
||
try
|
||
{
|
||
string path = Marshal.PtrToStringUni (pathPtr);
|
||
return path ?? string.Empty;
|
||
}
|
||
finally
|
||
{
|
||
if (pathPtr != IntPtr.Zero) CoTaskMemFree (pathPtr);
|
||
}
|
||
}
|
||
}
|
||
}
|