pb 1 рік тому
джерело
коміт
4807cef0f4
3 змінених файлів з 327 додано та 125 видалено
  1. 2
    1
      cliverse.js
  2. 28
    122
      index.js
  3. 297
    2
      win_verse.js

+ 2
- 1
cliverse.js Переглянути файл

@@ -42,7 +42,8 @@ function nodeShellExec() {
// D:\\chess\\instances\\elixir_01\\elxr/.elxr/run-1630002923584/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
// console.dir(args[2])
console.dir(`${args[0]} ${args[1].join(' ') }`)
console.log('nodeshellexec ::: ')
console.log(`${args[0]} ${args[1].join(' ') }`)

const child = spawn(...args);
var p = new Promise(function(resolve, reject){

+ 28
- 122
index.js Переглянути файл

@@ -262,6 +262,7 @@ function isWin(){ return /^win/.test(process.platform) }
if(isWin()) {
var win_verse = require('./win_verse')
var shell_verse = win_verse;
shell_verse.getVersion = getVersion
}
else {
var lin_verse = require('./lin_verse')
@@ -1339,7 +1340,8 @@ shell_verse.acquireElevationState().then((isElevated) => {
})()

return pending.then(( selectedinstance)=>{
// PB : TODO -- Maybe create a new instance so we can switch around for different values...
shell_verse.init({ statuslog, selectedinstance, processedArgs, runtimestamp, ENV })
var op = {
'h': () => { console.log(elxr.help()); return '-h' }
, 'clean' : () => {
@@ -3009,7 +3011,7 @@ shell_verse.acquireElevationState().then((isElevated) => {
// nodeShellExec('git', ['init'], { inherit : true});
if (0) {
// PB : TODO -- Special google chrome profile for tests etc.
nodeShellExec('pwd', { inherit: true });
nodeShellExec('pwd', { inherit: true });
// /c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe --user-data-dir=/c/chess/instances/elixir_01/data/Google/Chrome/User\ Data --profile-directory="chess"
// "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="C:\chess\instances\elixir_01\data\Google\Chrome\User Data" --profile-directory="chess" http://localhost:4200/admin/crud/create/item
// "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="C:\chess\instances\elixir_01\data\Google\Chrome\User Data" --profile-directory="chess" http://localhost:4200/tests/index.html?grep=loopback
@@ -3148,7 +3150,25 @@ shell_verse.acquireElevationState().then((isElevated) => {

g[processedArgs._[1]]();
}

, 'launchui' : () => {
console.log('-----------------------------')
console.log('Launching Elxir Admin Console')
console.log('-----------------------------')
// shell_verse.getchrome()

processedArgs.awaitrun = true;
return shell_verse.launchui()
// shell_verse.getchrome().then( chrome => {

// nodeShellExec( `"${chrome}"`, [
// '--profile-directory="chess"'
// , `${selectedinstance.root}/elixir-client/elxr-admin-console/html/index.html`], {
// inherit: true, shell: true
// , env: ENV
// })
// .catch(e => console.dir(e))
// })
}
, 'create' : () => { return createInstance(selectedinstance) }

, 'httpget' : () => {
@@ -3239,6 +3259,8 @@ shell_verse.acquireElevationState().then((isElevated) => {
elxrcmd.create( ca[1] )
})

shell_verse.cmds = cmds;

var __default = selectedinstance; // PB : TODO -- Eliminate __default references.
Tasq.addlistener(statuslog.statuslog)
@@ -4715,7 +4737,7 @@ shell_verse.acquireElevationState().then((isElevated) => {
}


var downloadsdir = '../Downloads';
var downloadsdir = shell_verse.downloadsdir;
var prerequisites = [
{
shellcmd: 'git',
@@ -4858,15 +4880,7 @@ shell_verse.acquireElevationState().then((isElevated) => {

prerequisites.forEach(p=>{ prerequisites[p.shellcmd] = p })

function ensureDirectoryExistence(filePath) {
var dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) {
return filePath;
}
ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname);
return filePath;
}
function ensureDirectoryExistence(filePath) { return shell_verse.ensureDirectoryExistence(filePath) }

var mainTasks = [];
function verifyAndInstallPrerequisites() {
@@ -5203,115 +5217,7 @@ shell_verse.acquireElevationState().then((isElevated) => {

}

function generateDependencies(){
// PB : TODO -- Keep only the last n runs...
// Currently it retains 2*n when proc needs to be relaunched in elevated mode !!!

ensureDirectoryExistence(`${selectedinstance.root}/.elxr/run-${runtimestamp}/download.bat`)
fs.writeFileSync(ensureDirectoryExistence(path.normalize(`${selectedinstance.root}/${downloadsdir}/readme.txt`)), `${getVersion()} Your local downloads for this instance`)
// PB : TODO include and build from files... using rollup..
var downloadbatch =
`::**************************************************************************
:Download_ <url> <File>
Powershell.exe ^
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'; ^
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols; ^
(New-Object System.Net.WebClient).DownloadFile('%1','%2')
exit /b
::**************************************************************************`
fs.writeFileSync(`${selectedinstance.root}/.elxr/run-${runtimestamp}/download.bat`, downloadbatch)

var windowselevate =
`
<html><HTA:APPLICATION ID="windowselevate" icon="#"/>
<script language="vbscript">
document.title = "elxr control panel"
self.ResizeTo 200,600
Sub Window_Onload
self.MoveTo (screen.availWidth - (document.body.clientWidth + 40)),10
End Sub

Set objShell = CreateObject("WScript.Shell")
Set objENV = objShell.Environment("Process")
dim NODE_ENV
NODE_ENV = objENV("NODE_ENV")
</script>

<script language="javascript">
//WINDOWSTATE="minimize" SHOWINTASKBAR="no" SYSMENU="no" CAPTION="no"
// https://devblogs.microsoft.com/scripting/how-can-i-pass-command-line-variables-to-an-hta-when-it-starts/
// alert(windowselevate.commandLine)
var args = windowselevate.commandLine.split('"').slice(3);
// alert(args)
var processedArgs = { _ : [] }
var namedArgs = [];
namedArgs.push('--wd=' + objENV('wd'))
// alert(namedArgs)
for(var item in args){
if(args[item].charAt(0) === '-'){
namedArgs.push(args[item])
var split = args[item].split('=');
processedArgs[split[0].slice(2)] = split[1] || true;
}
else processedArgs._.push(args[item]);
}
// args = args.forEach(function(item){ })
// alert('processedArgs._ : ' + processedArgs._);
// alert(processedArgs.runas);
// alert(objENV('wd'))
// PB : TODO -- Convert all the cli args back to string.
// __filename will sure we are launhed using the same entry point.
var cargs = (processedArgs.debug ? '--inspect-brk=9226' : '') + ' ${__filename.replace(/\\/g, '\\\\')} ' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ');
var shell = new ActiveXObject('shell.application');
// alert('launching node privilged. ' + processedArgs['nodepath'])
// shell.ShellExecute('cmd.exe', '/k where node', '', '', 10);
// shell.ShellExecute('cmd.exe', '/k notepad.exe', '', 'runas', 1);
// shell.ShellExecute('cmd.exe ', '/k node ', '', 'runas', 1);
// shell.ShellExecute('cmd.exe ', '/k node ' + cargs + '', '', 'runas', 1);
shell.ShellExecute('node', cargs, '', 'runas', 1);
// alert('/k node ' + cargs + '')
// shell.ShellExecute(processedArgs['nodepath'], cargs, '', 'runas', 1);
var fso = new ActiveXObject('Scripting.FileSystemObject');
window.onload = function() {
document.body.style.backgroundColor = 'black';
document.body.style.fontFamily = 'arial';
var log = document.createElement('div');
log.innerHTML='Please Wait';
function l(msg){ log.innerHTML+= msg; };
log.style.color = 'blue';
log.style.width = '95%';
log.id = 'log';
document.body.appendChild(log);
l('<Br/>Current config : ')
l('<Br/>NODE_ENV = ' + NODE_ENV)
l('<Br/>cmd = ' + processedArgs._[0])
processedArgs._[1] === 'use' ? l('<Br/>using = ' + processedArgs._[2]) : null;
l('<Br/><Br/>')
// alert(fso.GetAbsolutePathName("."))
var timer = function(){
l('.');
if(fso.FileExists("run.done")) {
fso.DeleteFile('run.done') // PB : TODO -- IPC through files is needed only for windows we need to do it per run...
close();
}
else window.setTimeout(timer, 1000);
};
window.setTimeout(timer, 3000);
};
</script>
</html>
`
fs.writeFileSync(`${selectedinstance.root}/.elxr/run-${runtimestamp}/windowselevate.hta`, windowselevate)
}
function generateDependencies(){ return shell_verse.generateDependencies() }

var startElxr = function() {
const retaincount = 2

+ 297
- 2
win_verse.js Переглянути файл

@@ -9,11 +9,24 @@ function elevatedRunIPCWriteMessage( target, m ) {
fs.writeFileSync(target, ', ' + JSON.stringify( m ), { 'flag': 'a+' })
}

function toHTML(l, x, r, ol, or){
ol = ol || '<div>'
or = or || '</div>'
l = l || '<div>'
r = r || '</div>'
if(Object.prototype.toString.call(x) === '[object Array]') {
var ahtml = []
x.forEach(xi => { ahtml.push( `${l}${xi}${r}` ) })
return `${ol}${ahtml.join('')}${or}`
}
}

var __isElevated = null;
var shell_verse = {
// getCommonTask is agnostic of whether we are running in an elevated shell or not. It runs in either case.
getCommonTask( taskToRun ){ return ()=>{ return shell_verse.runTask(taskToRun) }}
init( o ){ Object.assign(this, o) }
, downloadsdir : '../Downloads'
, getCommonTask( taskToRun ){ return ()=>{ return shell_verse.runTask(taskToRun) }}
, runTask : ( taskToRun ) => {
if (__isElevated) return shell_verse.elevatedRunner( taskToRun )
else return shell_verse.runNonElevated( taskToRun )
@@ -225,9 +238,291 @@ var shell_verse = {
console.error('Run log error probably was not created by runas : ' + e)
}
})
.catch(err => console.error('Elevation failed : ' + err));
.catch(err => console.error('Elevation failed : ' + err));
})
}
, launchui() {
// PB : TODO -- Multiple parallel requests should be queued into a batch and serialized as a single promise.
// PB : TODO -- cleanup elevated execution code from here. This is a non elevated hta.

var processedArgs = this.processedArgs
// Wait for the runas to complete before we read it.
try {
fs.unlinkSync('run.done') // Need a unique file for aech elevated run.
}
catch (e) { } //Ignore

console.log(this.processedArgs.awaiturn)

// Find node path to send to hta.
return nodeShellExec('where', ['node']).then(r => {
var namedArgs = [];
console.log('result : ' + JSON.stringify(r))
Object.keys(processedArgs).forEach((v) => { v != '_' ? namedArgs.push('--' + v + '=' + processedArgs[v]) : null; })
// PB : TODO -- Convert all the cli args back to string.
var _args = []
if(processedArgs._[0] === 'launchui' ) { _args = processedArgs._.slice(1); _args.splice(0,0, 'pull') } // Default command.
else _args = processedArgs._;
var args = [ path.normalize(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/windowselevate.hta`) ].concat(_args)
namedArgs.length > 0 ? args = args.concat(namedArgs.join(' ')) : null;
// args.push('--runas=self');
var spawntimestamp = (new Date()).getTime()
args.push(`--runtimestamp=${spawntimestamp}`);

// args.push('--nodepath=' + r.messages[r.messages.length - 1])
// if (!processedArgs.node_env) args.push('--node_env=' + ENV.NODE_ENV)
// if (processedArgs.debug) args.push('--debug=true') // Enable to debug elevated..
// console.dir(processedArgs._)
// console.dir(namedArgs.join(' '))
console.dir(args)
// throw 'test'

return nodeShellExec('MSHTA', [`"${args.join('" "')}"`]
, {
inherit: true
, shell: true
, env: this.ENV
// , runas: 'self'
// , title: `runas`
}
).then(() => {
// runas returned.
try {
// PB : TODO -- Log is comma prefixed. Needs to be proper JSON.
var runlogjson = `${this.selectedinstance.root}/.elxr/run-${spawntimestamp}/run.log`
var runaslog = JSON.parse('[' + fs.readFileSync(runlogjson, { flags: 'a+' }) + ']');
try { fs.unlinkSync(runlogjson) } catch(e){ } // PB : TODO -- Have a unique file for each elevated run.
// console.log( "runaslog : " + runaslog.length )
// Assemble elevated run results into the main run log
runaslog.forEach((logEntry) => {
this.statuslog.statuslog(logEntry.success ? null : logEntry, logEntry)
logEntry.success ? (console.log(['success :' + (logEntry.result || logEntry.success)]), console.log((logEntry.messages || []).join(' '))) : (console.error(['error :' + logEntry.result]), console.error((logEntry.messages || []).join(' ')))
})
}
catch (e) {
// We must have a runas log
this.statuslog.statuslog(e)
console.error('Run log error probably was not created by runas : ' + e)
}
})
.catch(err => console.error('Elevation failed : ' + err));
})
}
, ensureDirectoryExistence(filePath) {
var dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) {
return filePath;
}
this.ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname);
return filePath;
}

, generateDependencies(){
// PB : TODO -- Keep only the last n runs...
// Currently it retains 2*n when proc needs to be relaunched in elevated mode !!!

this.ensureDirectoryExistence(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/download.bat`)
fs.writeFileSync(this.ensureDirectoryExistence(path.normalize(`${this.selectedinstance.root}/${this.downloadsdir}/readme.txt`)), `${this.getVersion()} Your local downloads for this instance`)
// PB : TODO include and build from files... using rollup..
var downloadbatch =
`::**************************************************************************
:Download_ <url> <File>
Powershell.exe ^
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'; ^
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols; ^
(New-Object System.Net.WebClient).DownloadFile('%1','%2')
exit /b
::**************************************************************************`
fs.writeFileSync(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/download.bat`, downloadbatch)

var windowselevate =
`
<html><HTA:APPLICATION ID="windowselevate" icon="#"/>
<script language="vbscript">
document.title = "elxr control panel"
self.ResizeTo 1024,1000
Sub Window_Onload
self.MoveTo (screen.availWidth - (screen.availWidth/2 + 40)),10
End Sub

Set objShell = CreateObject("WScript.Shell")
Set objENV = objShell.Environment("Process")
dim NODE_ENV
NODE_ENV = objENV("NODE_ENV")
</script>

<script language="javascript">
//WINDOWSTATE="minimize" SHOWINTASKBAR="no" SYSMENU="no" CAPTION="no"
// https://devblogs.microsoft.com/scripting/how-can-i-pass-command-line-variables-to-an-hta-when-it-starts/
// alert(windowselevate.commandLine)
var args = windowselevate.commandLine.split('"').slice(3);
// alert(args)
var processedArgs = { _ : [] }
var namedArgs = [];
namedArgs.push('--wd=' + objENV('wd'))
// alert(namedArgs)
for(var item in args){
if(args[item].charAt(0) === '-'){
namedArgs.push(args[item])
var split = args[item].split('=');
processedArgs[split[0].slice(2)] = split[1] || true;
}
else processedArgs._.push(args[item]);
}
var awaitrun = true;
if(!processedArgs.awaitrun) {
awaitrun = false;
delete processedArgs.awaitrun
}
// args = args.forEach(function(item){ })
// alert('processedArgs._ : ' + processedArgs._);
// alert(processedArgs.runas);
// alert(objENV('wd'))
// PB : TODO -- Convert all the cli args back to string.
// __filename will sure we are launhed using the same entry point.
var cargs = (processedArgs.debug ? '--inspect-brk=9226' : '') + ' ${__filename.replace(/\\/g, '\\\\').replace("win_verse", "index")} ' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ');
var shell = new ActiveXObject('shell.application');
// alert('launching node privilged. ' + processedArgs['nodepath'])
// shell.ShellExecute('cmd.exe', '/k where node', '', '', 10);
// shell.ShellExecute('cmd.exe', '/k notepad.exe', '', 'runas', 1);
// shell.ShellExecute('cmd.exe ', '/k node ', '', 'runas', 1);
// shell.ShellExecute('cmd.exe ', '/k node ' + cargs + '', '', 'runas', 1);
// alert(cargs)
function run(runas){ shell.ShellExecute('node', cargs, '', runas, 1); }
if(!awaitrun) { run('runas') }

var log = document.createElement('div');
log.innerHTML='Please Wait';
function l(msg){ log.innerHTML+= msg; };
// log.style.color = 'blue';
log.style.width = '95%';
log.id = 'log';

function endconsole(from){
// alert('endconsole ' + from)
if(fso.FileExists("run.done")) {
fso.DeleteFile('run.done') // PB : TODO -- IPC through files is needed only for windows we need to do it per run...
}
// alert('closing window')
window.close();
};
var timer = function(){
// alert('here')
l('.');
if(fso.FileExists("run.done")) {
endconsole('timer')
}
else window.setTimeout(timer, 1000);
};

// alert('/k node ' + cargs + '')
// shell.ShellExecute(processedArgs['nodepath'], cargs, '', 'runas', 1);
var fso = new ActiveXObject('Scripting.FileSystemObject');

function i(html){ var e = document.createElement('div'); e.innerHTML = html; document.body.appendChild(e); };

// window.onbeforeunload = function (e) {
// endconsole('onbeforeunload')
// };
window.onload = function() {
document.body.style.backgroundColor = 'black';
document.body.style.fontFamily = 'arial';
document.body.style.color = 'cyan';
var cmds = document.createElement('div');
cmds.innerHTML = '';
cmds.w = function(msg){ cmds.innerHTML+= msg; };
cmds.w('<Br/>Current config : ')
// cmds.w('<div style="width:50%" onclick="endconsole()">X</div>' )
cmds.w('<input type="button" value="Close Console" onclick="endconsole()">')
cmds.w('<Br/>NODE_ENV = ' + NODE_ENV)
var namedArgs = [];
for(var v in processedArgs){
if(v != '_' && v!== 'runtimestamp') {
namedArgs.push('--' + v + '=' + processedArgs[v])
}
}
// cmds.w('<Br/>cmd = ' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ') )
cmds.w('<Br/><Br/>')
cmds.w('cmd = <input style="width:80%" type="text" value="' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ') + '"></input> <input type="button" value="Run" onclick="run()"></input>')
cmds.w('${toHTML('<option>', Object.keys(this.cmds), '</option>', '<select>', '</select>')}');

// cmds.style.color = 'blue';
// processedArgs._[1] === 'use' ? l('<Br/>using = ' + processedArgs._[2]) : null;

document.body.appendChild(cmds);
document.body.appendChild(log);

// alert(fso.GetAbsolutePathName("."))
window.setTimeout(timer, 3000);
};
</script>
</html>
`
fs.writeFileSync(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/windowselevate.hta`, windowselevate)
}
, getchrome(){
// Chrome install location from registry.
return shell_verse.regread("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe\\").then(chromepath => {
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe
console.log(chromepath)
return chromepath
});
}
, regread(s){
var uniquerun = (new Date()).getTime()
var out = `${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/${uniquerun}-regread.out`
var outescaped = out.replace(/\\/g,"\\\\")
// console.log('out ::: ' + out)
fs.writeFileSync(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/${uniquerun}-regread.js`,
`
// WScript.Echo('------------UNNAMED-----------')
// WScript.Echo(WScript.Arguments.Item(0))
argEnumerator = new Enumerator(WScript.Arguments.Unnamed)
var args = []
for(; !argEnumerator.atEnd(); argEnumerator.moveNext()){
args.push('' + argEnumerator.item() + '')
// WScript.Echo('-arg-' + argEnumerator.item() + '-arg-') // Value
}

// WScript.Echo(args[0])
var objShell = WScript.createobject("wscript.shell")
if(!args[0]) {
WScript.Echo( '' )
}
else {
WScript.Echo(args[0])
var read = objShell.RegRead(args[0])
try {
var fs = new ActiveXObject('Scripting.FileSystemObject');
var fh = fs.CreateTextFile('${outescaped}', true);
fh.WriteLine(read);
fh.Close();
}
catch(e){ WScript.Echo(e.message) }
// WScript.Echo( read )
}
`
)
return nodeShellExec('cscript', [path.normalize(`${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/${uniquerun}-regread.js`), `${s}`])
.then(read => {
// console.log("REGREAD RESULT : " + read)
// console.dir(read)
if(read.success) {
return (fs.readFileSync(out) + "").trim()
}
else throw 'regread failed'
})
}
, iswin(){ return true}
, islin(){ return false}
}

Завантаження…
Відмінити
Зберегти