How to open a html file whenever it is modified? - windows

I am faced with the issue of IIS express stopping abruptly without any stack trace while debugging in local.
I have found a work around for this by writing the stack trace to a html file.
string file = #"C:\Users\INLASKD\Desktop\ExceptionHandlerError.html";
using (FileStream fs = new FileStream(file, FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.WriteLine(sb.ToString());
}
}
Now, I want to open this ExceptionHandlerError.html automatically everytime its modified when IIS Express stops.
I want bat file or a script to automate this. How can I go about this?
Note: I am connected to a network that doesn't allow administrator access and can't access event viewer.

After some research, I was able to open the browser right after writing it to the file with
System.Diagnostics.Process.Start(file);
Final code is as below:
string file = #"C:\Users\iraacn-9ajm\Desktop\ExceptionHandlerError.html";
using (FileStream fs = new FileStream(file, FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.WriteLine(sb.ToString());
}
}
System.Diagnostics.Process.Start(file);

You should be able to use this:
#echo off
set "file=C:\Users\INLASKD\Desktop\ExceptionHandlerError.html"
:loop
attrib "%file%" | findstr /B /L A 1>nul
if %errorlevel% equ 0 (
::open the file here
start "" "%file%"
attrib -A "%file%"
)
timeout /t 2 /nobreak >nul
goto loop

Related

How to get CMD output in HTA file within JavaScript

I run some CMD commands in my HTA file like
<script>
var WShell = new ActiveXObject('WScript.Shell');
WShell.run('cmd /c the_first_command');
WShell.run('cmd /c the_second_command');
</script>
and the first command may need a time to be fully executed, for example a few seconds
I need to run the next command only after the CMD output says that the previous task is fully completed.
As I understand, after the first command I can run an interval for example
var timer = setInterval(function() {
var cmd_output_of_the_first_command = ???;
if(~cmd_output_of_the_first_command.indexOf('A text about the task is completed')) {
clearInterval(timer);
WShell.run('cmd /c the_second_command');
}
}, 500);
So the question is how to get the CMD output?
Ok, I've found the answer:
var WShell = new ActiveXObject('WScript.Shell');
var WShellExec = WShell.Exec('cmd /c the_first_command');
var WShellResult = WShellExec.StdOut.ReadAll();
if(~WShellResult.indexOf('A text about the task is completed')) {
WShell.Run('cmd /c the_second_command');
}
No need in any interval
OR
just
execute CMD synchronously one by one without the need to check CMD output
WShell.Run('cmd /c the_first_command', 0, true);
WShell.Run('cmd /c the_second_command', 0, true);

Get Explorer's children in batch

I created folder shortcuts for my taskbar and I would like them to stop launching a new explorer every time
So I decided to create a batch script, howover I can not get the kids from explorer.exe
#echo off
pushd
tasklist /nh /fi "imagename eq explorer.exe C:\Users\danil\Desktop\ISO" | find /i "explorer.exe C:\Users\danil\Desktop\ISO" > nul ||(start explorer.exe C:\Users\danil\Desktop\ISO)
The issue with your attempt is that tasklist will list only one instance of explorer.exe but not the titles of each window openned.
With some edits over this I've created listWindows.bat - it will list all visible windows names and their coresponding executable. So you can try this:
call listWindows.bat|findstr /i /b /e "explorer::Downloads" >nul 2>nul || (
start "" explorer.exe "C:\Users\%username%\Downloads"
)
To check the windows you need to start you can just try this:
call listWindows.bat|findstr /i /b "explorer::"
You cannot check the opening folders by checking the command line options, because the arguments stay the same across the whole lifetime of the process even after you changed to some other folders in that window. You need to use scriptable shell objects to get the current address.
Here's a PowerShell script to open a folder if it's not already opened in explorer
$folder = 'C:\Users\danil\Desktop\ISO'
$folderOpened = $false
foreach ($w in (New-Object -ComObject Shell.Application).Windows()) {
if ($w.LocationURL -ieq ([uri]$folder).AbsoluteUri) {
$folderOpened = $true; break
}
}
if (-not $folderOpened) { Invoke-Item $folder } # or start $folder
Below is an equivalent hybrid batch-jscript snippet
#if (#CodeSection == #Batch) #then
#echo off
cscript //e:jscript //nologo "%~f0" %*
exit /b
#end
// JScript Section
var objShell = new ActiveXObject("shell.application");
var objShellWindows;
objShellWindows = objShell.Windows();
if (objShellWindows != null)
{
// the folder you want to open
var folder = "file:///C:/Users/danil/Desktop/ISO";
var folderOpened = 0;
for (var objEnum = new Enumerator(objShellWindows);
!objEnum.atEnd(); objEnum.moveNext())
{
if (folder == objEnum.item().LocationUrl)
{
folderOpened = 1;
break;
}
}
if (!folderOpened) // open the folder if it's not already opened
objShell.Explore(folder); // or objshell.Open(folder)
}
Each explorer window is represented by an InternetExplorer object that can be retrieved from the Shell.Windows() collection. You need to use a file URI scheme instead of a normal Windows path, but it works. Of course you can even further change it to switch to the folder window if it's being opened. You can also use VBS or any other languages that support scriptable shell objects
Update:
You can avoid the file URI scheme by changing objEnum.item().LocationUrl to objEnum.item().Document.Folder.Self.Path
In the PowerShell version above it means changing
if ($w.LocationURL -ieq ([uri]$folder).AbsoluteUri) {
to
if ($w.Document.Folder.Self.Path -ieq $folder) {

How can I get the current active window at the time a batch script is run?

I have a batch script I want to run with hotkeys, and this script is supposed to make some actions in the active window (for example, creating a particular set of folders, or lowercase all names of the files inside the folder). So the script needs to refer to the active window when it's called.
I have tried to leave the "Start in" field of the alias empty, but echoing %cd% always print "C:\Windows\System32" instead of the current active window.
You can lookup which process got the window in foreground using pinvoke of user32.dll.
I've used this trick for system.window.forms.sendkeys method in a script:
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class Tricks {
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
}
"#
$a = [tricks]::GetForegroundWindow()
get-process | ? { $_.mainwindowhandle -eq $a } # in my case:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
161 7 13984 15820 91 9,75 7720 Console
For anyone looking for a non-Powershell solution, here's a batch script that uses cscript to invoke a block of JScript. The JScript creates a new child process, gets its PID, then walks up the ParentProcessID line of ancestors until it gets to explorer.exe, then returns the PID of the direct child. It ought to return the correct PID for the console window in which the script runs, even if there are multiple instances of cmd.exe or cscript.exe running.
What can I say? I was feeling creative today.
#if (#a==#b) #end /* JScript multiline comment
:: begin batch portion
#echo off
setlocal
for /f "delims=" %%I in ('cscript /nologo /e:Jscript "%~f0"') do (
echo PID of this console window is %%I
)
goto :EOF
:: end batch portion / begin JScript */
var oShell = WSH.CreateObject('wscript.shell'),
johnConnor = oShell.Exec('%comspec% /k #echo;');
// returns PID of the direct child of explorer.exe
function getTopPID(PID, child) {
var proc = GetObject("winmgmts:Win32_Process=" + PID);
// uncomment the following line to watch the script walk up the ancestor tree
// WSH.Echo(proc.name + ' has a PID of ' + PID);
return (proc.name == 'explorer.exe') ? child : getTopPID(proc.ParentProcessID, PID);
}
var PID = getTopPID(johnConnor.ProcessID);
johnConnor.Terminate();
// send the console window to the back for a second, then refocus, just to show off
oShell.SendKeys('%{ESC}');
WSH.Sleep(1000);
oShell.AppActivate(PID);
// output PID of console window
WSH.Echo(PID);

Get DOS path instead of Windows path

In a Windows CMD.exe command line, how can I get the full DOS name/short name (a.k.a. 8.3 format) of the directory I am in?
For example, if I am in the directory C:\Program Files\Java\jdk1.6.0_22, I want to display it's short name C:\PROGRA~1\Java\JDK16~1.0_2.
I know running dir /x will give me the short names of files/directories in the current directory but I haven't been able to find a way to display the full path of the current directory in short name format. I'm having to work my way through the path from the root, directory by directory, running dir /x in each.
I'm sure there is an easier way to do this?
for %I in (.) do echo %~sI
Any simpler way?
You could also enter the following into a CMD window:
dir <ParentDirectory> /X
Where <ParentDirectory> is replaced with the full path of the directory containing the item you would like the name for.
While the output is not a simple as Timbo's answer, it will list all the items in the specified directory with the actual name and (if different) the short name.
If you do use for %I in (.) do echo %~sI you can replace the . with the full path of the file/folder to get the short name of that file/folder (otherwise the short name of the current folder is returned).
Tested on Windows 7 x64.
In windows batch scripts, %~s1 expands path parameters to short names. Create this batch file:
#ECHO OFF
echo %~s1
I called mine shortNamePath.cmd and call it like this:
c:\>shortNamePath "c:\Program Files (x86)\Android\android-sdk"
c:\PROGRA~2\Android\ANDROI~1
Edit: here's a version that uses the current directory if no parameter was supplied:
#ECHO OFF
if '%1'=='' (%0 .) else echo %~s1
Called without parameters:
C:\Program Files (x86)\Android\android-sdk>shortNamePath
C:\PROGRA~2\Android\ANDROI~1
Being a programmer made this 10-minute Winform project. It's been useful for me. Making this app to a context menu for file explorer would save more clicks.
Form1.cs:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace ToShortPath
{
public partial class Form1 : Form
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string path,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder shortPath,
int shortPathLength
);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Show the dialog and get result.
var openFileDialog1 = new OpenFileDialog();
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
textBox1.Text = openFileDialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
var openFileDialog1 = new FolderBrowserDialog();
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
textBox1.Text = openFileDialog1.SelectedPath;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
StringBuilder shortPath = new StringBuilder(65000);
GetShortPathName(textBox1.Text, shortPath, shortPath.Capacity);
textBox2.Text = shortPath.ToString();
}
}
}
Form1.Designer.cs:
namespace ToShortPath
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(69, 13);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(516, 53);
this.textBox1.TabIndex = 0;
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(69, 72);
this.textBox2.Multiline = true;
this.textBox2.Name = "textBox2";
this.textBox2.ReadOnly = true;
this.textBox2.Size = new System.Drawing.Size(516, 53);
this.textBox2.TabIndex = 1;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(7, 35);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(56, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Long Path";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(7, 95);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(57, 13);
this.label2.TabIndex = 3;
this.label2.Text = "Short Path";
//
// button1
//
this.button1.AutoSize = true;
this.button1.Location = new System.Drawing.Point(591, 13);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(40, 53);
this.button1.TabIndex = 4;
this.button1.Text = "File";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.AutoSize = true;
this.button2.Location = new System.Drawing.Point(637, 12);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(46, 53);
this.button2.TabIndex = 5;
this.button2.Text = "Folder";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(687, 135);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Short Path";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
}
}
run cmd.exe and do the following:
> cd "long path name"
> command
Then command.com will come up and display only short paths.
source
Kimbo's answer is perfect for normal files.
for %I in (.) do echo %~sI
For MsDos file names on HardLinks
The hard links created with mklink /H <link> <target> will not have an MsDos short file name.
In case you dir /X and you discover that missing short name you should expect the followings:
d:\personal\photos-tofix\2013-proposed1-bad>dir /X
Volume in drive D has no label.
Volume Serial Number is 7C7E-04BA
Directory of d:\personal\photos-tofix\2013-proposed1-bad
03/02/2015 15:15 <DIR> .
03/02/2015 15:15 <DIR> ..
22/12/2013 12:10 1,948,654 2013-1~1.JPG 2013-12-22--12-10-42------Bulevardul-Petrochimiștilor.jpg
22/12/2013 12:10 1,899,739 2013-12-22--12-10-52------Bulevardul Petrochimiștilor.jpg
Normal file
In this case
> for %I in ("2013-12-22--12-10-42------Bulevardul-Petrochimiștilor.jpg") do echo %~sI
I've got what I expected
d:\personal\PH124E~1\2013-P~3\2013-1~1.JPG
Hard link file
In this case
> for %I in ("2013-12-22--12-10-52------Bulevardul-Petrochimiștilor.jpg") do echo %~sI
I've got the normal MsDos path but the normal filename.
d:\personal\PH124E~1\2013-P~3\2013-12-22--12-10-52------Bulevardul-Petrochimiștilor.jpg`
A someone more direct answer is to fix the bug.
%SPARK_HOME%\bin\spark-class2.cmd; Line 54
Broken: set RUNNER="%JAVA_HOME%\bin\java"
Windows Style: set "RUNNER=%JAVA_HOME%\bin\java"
Otherwise, the RUNNER ends up with quotes, and the command
"%RUNNER%" -Xmx128m ...
ends up with double-quotes. The result is that the Program and File are treated as separate parameters.
similar to this answer but uses a sub-routine
#echo off
CLS
:: my code goes here
set "my_variable=C:\Program Files (x86)\Microsoft Office"
echo %my_variable%
call :_sub_Short_Path "%my_variable%"
set "my_variable=%_s_Short_Path%"
echo %my_variable%
:: rest of my code goes here
goto EOF
:_sub_Short_Path
set _s_Short_Path=%~s1
EXIT /b
:EOF
$fso = New-Object -com scripting.filesystemobject
$fso.GetFolder('c:\Program Files (x86)').ShortName()
PROGRA~2
Inspired by Dr. Scripto's answer
if via a batch file use:
set SHORT_DIR=%~dsp0%
you can use the echo command to check:
echo %SHORT_DIR%
Place this script somewhere in the windows path. I called mine getshort.bat and placed it in the System32 folder.
To use this you must pass a single path parameter after calling the scrip in cmd.exe window.
So open cmd.exe and type something like getshort.bat "C:\folder\file name with spaces.ext" You must double-quote paths with spaces otherwise not necessary.
The script will take the path you supplied and store the shortname in a temporary text file with two versions, version 1 has quotes around the short path, and the other version does not.
I use notepad++ to open txt files so if you do not use that program you need to change the line START "" /MAX NOTEPAD++ "%TMP%\Test.txt" and replace notepad++ with your editor's name.
#ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
COLOR 0A
:----------------------------------------------------------------------------------
REM SET THE CD VARIABLE EQUAL TO THE FIRST PARAMATER YOU PASSED THE SCRIPT
:: ..WHICH WAS A FILE PATH OF YOUR CHOOSING...
CD=%1
:----------------------------------------------------------------------------------
:: DELETE ANY LEFTOVERS FROM PRIOR RUNS
IF EXIST "%TMP%\Test.txt" DEL /F /Q "%TMP%\Test.txt"
:----------------------------------------------------------------------------------
:: USE THE FOR COMMAND TO CALL A SUBROUTINE TO STORE THE SHORT NAMES WITH AND WITHOUT QUOTES
FOR %%1 IN ("%CD%") DO (
SET ARG1="%%~s1"
SET ARG2=%%~s1
CALL :CREATE_TXTFILE ARG1 ARG2
START "" /MAX NOTEPAD++ "%TMP%\Test.txt"
GOTO :EOF
)
:----------------------------------------------------------------------------------
REM USE THIS SUB-ROUTINE TO STORE THE SHORTNAMES INSIDE THE A TXT FILE
:CREATE_TXTFILE
(
ECHO %ARG1%
ECHO %ARG2%
)>"%TMP%\Test.txt"
:: THE NEXT LINE WILL RETURN THE SCRIPT TO THE LINE BELOW THE CALL COMMAND ABOVE AND CONTINUE EXECUUTION AS NORMAL
:: NOTEPAD++ WILL ATTEMPT TO FIND AND OPEN THE NEWLY CREATED TXT FILE WITH THE SHORTNAMES INSIDE
:: CHANGE TO WHATEVER TEXT EDITOR YOU HAVE TO OPEN TXT FILES IF YOU DONT HAVE NOTEPAD++
EXIT /B
use this link, it will automatically convert any path you give to any format
https://pathconverter-pp.azurewebsites.net

How can I move files to the Recycle Bin in a Windows batch script or Perl?

I've got a Windows XP batch script which cleans some directories, but I would like to move the deleted files to trash instead of using plain del. How is this done?
It looks like the only languages I can use for this is plain batch or Perl.
use Win32::FileOp qw(Recycle);
Recycle(#ARGV);
Write a VBS script (Original Link) then call it with MyDelScript.vbs
function main()
{
if (WScript.Arguments.length != 1)
{
WScript.Echo("<Insert informative error message here>");
return;
}
var Path = WScript.Arguments(0);
var Shell = WScript.CreateObject("Shell.Application");
var Item = Shell.Namespace(0).ParseName(Path);
Item.InvokeVerb("delete");
}
The Win32::FileOp module has a Recycle function. From the docs:
Recycle #filenames
Send the files into the recycle bin. You will not get any confirmation dialogs.
Returns true if successful.
It can be done like this with plain batch and embedded VBScript. Put the following code into a file called recycle.cmd:
<!-- : Begin batch script
#echo off
if "%1"=="" (
echo Usage: %~nx0 FILE_TO_RECYCLE[...]
echo This script puts files into the recycle bin
exit /b 1
)
cscript //nologo "%~f0?.wsf" %*
exit /b %errorlevel%
----- Begin embedded wsf script --->
<job><script language="VBScript">
Set app = WScript.CreateObject("Shell.Application")
Set fso = CreateObject("Scripting.FileSystemObject")
For Each arg In WScript.Arguments
If fso.FileExists(arg) Then
Set file = fso.GetFile(arg)
Set folderItem = app.Namespace(0).ParseName(file.Path)
folderItem.InvokeVerb("delete")
Else
WScript.Echo "File not found: " & arg
End If
Next
</script></job>
Example:
echo This file is dirt.> dirt.txt
echo This file is trash.> trash.txt
recycle dirt.txt trash.txt
As you can see the script allows recycling multiple files with one command.
It does not suppport the wildcards * and ? though.
The idea of embedding VBScript inside a batch file is taken from dbenham's answer to Is it possible to embed and execute VBScript within a batch file without using a temporary file? (scroll down to UPDATE 2014-04-27).
You could use the "recycle" utility which is part of CmdUtils from MaDdoG Software. From the page listing -
Recycle, a safe replacement for the DEL command, that sends files to the recycle bin instead of deleting them. Recycle is also more flexible than DEL; you can specify multiple files at once (or use wildcards), and you can recycle whole directories at once (be careful!)
I would suggest you try its various switches before you incorporate it into your script - there is quite a bit of deviation from the default behaviour of the "del" command.
UPDATE: Contrary to my original claim that the following code does not work, it indeed seems to work. I just forgot that the file I wanted to delete was not in $ENV{TEMP} but a subdirectory of $ENV{TEMP}. The problem is, the file does not go to the Recycle Bin.
The right solution is to use Win32::FileOp but I am going to leave this script here as an example of how to use Win32::API and Win32::API::Struct. I would appreciate it if anyone can point out what I am doing wrong. For your reference:
SHFileOperation: http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx
LPSHFILEOPSTRUCT: http://msdn.microsoft.com/en-us/library/bb759795(VS.85).aspx
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions qw( catfile );
use Win32::API;
Win32::API::Struct->typedef(
SHFILEOPSTRUCT => qw(
HWND hwnd;
UINT wFunc;
LPCTSTR pFrom;
LPCTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCTSTR lpszProgressTitle;
)
);
Win32::API->Import(
shell32 => q{ int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp ) }
);
my $op = Win32::API::Struct->new( 'SHFILEOPSTRUCT' );
$op->{wFunc} = 0x0003; # FO_DELETE from ShellAPI.h
$op->{fFlags} = 0x0040; # FOF_ALLOWUNDO from ShellAPI.h
my $to_delete = catfile( $ENV{TEMP}, "test.file" );
$op->{pFrom} = $to_delete . "\0\0";
my $result = SHFileOperation( $op );
if ( $result ) {
warn sprintf "The operation failed: %4.4X\n", $result;
}
else {
if ( $op->{fAnyOperationsAborted} ) {
warn "Operation was aborted\n";
}
else {
warn "The operation succeeded\n";
}
}
__END__

Resources