Comments (19)
For the issue around quoting rules, you can access the invoked command with $MyInvocation
. This seems to work for me so far:
function Invoke-Gsudo {
gsudo.exe ($MyInvocation.Line -replace "^$($MyInvocation.InvocationName)\s+" -replace '"','""')
}
❯ set-alias sudo Invoke-Gsudo
❯ sudo echo "abc def"
abc def
❯ _
from gsudo.
So one thing you could do is to create a proxy command for Invoke-Expression to add an -Elevate parameter. Inventing new verbs (elevate) is frowned upon in the powershell world. You can have powershell automagically generate a wrapper function and pipe it to the clipboard like so:
[System.Management.Automation.ProxyCommand]::Create((gcm invoke-expression)) | clip
You end up with a function body (which you would wrap in a function Invoke-Expression { ... }
block.) Functions have precedence over native Cmdlets.
[CmdletBinding(HelpUri='https://go.microsoft.com/fwlink/?LinkID=2097030')]
param(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[string]
${Command})
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Invoke-Expression', [System.Management.Automation.CommandTypes]::Cmdlet)
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
<#
.ForwardHelpTargetName Microsoft.PowerShell.Utility\Invoke-Expression
.ForwardHelpCategory Cmdlet
#>
You would then add a new switch parameter to the param block, [switch]$Elevate
. This is a reasonable way to add new functionality to an out of the box cmdlet. But given that you're pushing the work to gsudo, you'd rip out the steppable pipeline stuff and replace with your own marshalling script. Just an idea.
from gsudo.
btw, powershell.exe and pwsh.exe can automatically deserialize psserialized objects from a native command (e.g. cmd batch, exe or other out of proc process) if the stdin stream is prefixed with a special marker sequence. Check this out:
Create a batch file foo.cmd
(escaping < and > with ^)
@echo #^< CLIXML
@echo ^<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"^>^<I32^>42^</I32^>^</Objs^>
Now, pipe this command to foreach %
.\foo.cmd | % { $_ }
42
Magic!
So if your out of proc elevation serializes the output, then we could pipe an inline elevated expression to another cmdlet/function without having to insert ugly deserialization code.
from gsudo.
Oh this could also help - you can get powershell to serialize AND add the magic marker itself like this:
pwsh -noprofile -outputformat xml -command { gi c:\windows }
#< CLIXML
<Objs ... >
Example rehydrating in another pwsh process:
pwsh -noprofile -outputformat xml -command { gi c:\windows } | pwsh -noprofile -command { $input | % { $_ } }
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2020-06-15 2:58 PM Windows
from gsudo.
I'd be happy to contribute, but that said, I haven't played with your magical powershell elevation. I suspect it secretly sends the work to an out of process instance of powershell. Am I right? Trying to pretend that a scriptblock is in the same lexical scope as the caller might lead to all kinds of weird situations as the variables wouldn't exist in that other runspace's sessionstate. Or are you doing something sneakier?
from gsudo.
e.g. Elevate-Command.ps1
$a = 10
Elevate-Command -ScriptBlock { $b = $using:a ; $b = $b+1 ; $b }
returns 11
!
from gsudo.
I bet people would throw me stones if It doesnt respect the verb-noun form.
The correct way is to name it in verb-noun (Invoke-Gsudo) manner and set alias to whatever (gsudo).
from gsudo.
The -EncodedCommand
parameter seems helpful here too. It would save much of the quoting headaches.
I use it in this function I stole from Lee Holmes in order to run psexec
, sysinternals tool.
Here is the applicable piece of code which appears in the help
for pwsh
and powershell
, i think.
## $expression -eq [scriptblock]
## Convert the command into an encoded command for PowerShell
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes($expression)
$encodedCommand = [Convert]::ToBase64String($commandBytes)
$commandLine += "-EncodedCommand $encodedCommand"
from gsudo.
Matt! You anticipated me. I will post what I had in draft and then address your comments:
Hi again!
Sorry for not having the time to focus on gsudo as much as I wanted lately. Let's try to move this one forward a little bit.
There is an experimental Invoke-gsudo.ps1
that I want to open for early testing. Put it in your path, preferable in gsudo's folder (get-command gsudo.exe | % { (get-item $_.Source ).Directory.FullName }
)
This is a glimpse of current status:
.DESCRIPTION
Serializes a scriptblock and executes it in an elevated powershell.
The ScriptBlock runs in a different process, so it can´t read/write variables from the invoking scope.
If you reference a variable in a scriptblock using the `$using:variableName` it will be replaced with it´s serialized value.
The elevated command can accept input from the pipeline with $Input. It will be serialized, so size matters.
The script result is serialized, sent back to the non-elevated instance, and returned.
Optionally you can check for "$LastExitCode -eq 999" to find out if gsudo failed to elevate (UAC popup cancelled)
.EXAMPLE
PS> Get-Process notepad | Invoke-gsudo { Stop-Process }
PS> Invoke-gsudo { return Get-Content 'C:\My Secret Folder\My Secret.txt'}
PS> $a=1; $b = Invoke-gsudo { $using:a+10 }; Write-Host "Sum returned: $b";
Sum returned: 11
Problems/Challenges
-
Steppable input is supported, but serialized all at once. (It's not streamed one-by-one). Large input will probably cause issues.
I don't think this is such a big issue at this point since the user could move the elevation boundary to minimize the serialization and performance hit. -
Commands
return
issue: EDIT: FIXED
As of now, Invoke-gsudo is requiring an extra 'return' statement on some cases. For example:PS C:\> Invoke-Command { Get-Content C:\Test.txt }
for reference, Invoke-Command works (returns file content).PS C:\> Invoke-gsudo { Get-Content C:\Test.txt }
doesn't work, returns nothing.PS C:\> Invoke-gsudo { return Get-Content C:\Test.txt }
works.PS C:\> Invoke-gsudo { Get-Content C:\Test.txt ; 1 }
works, returns the content and a 1.
-
Exception handling:
I'm not able to distinguish between Terminating (Invoke-gsudo { throw}
) and non-terminating errors ( Invoke-gsudo { Write-Error 1; Write-Error 2;}
) here
and I think the ErrorAction needs to be Stop for the formers so they trigger catch blocks.
- Only works in TokenMode, at least for now.
Basically dont change gsudo settings like: SecurityEnforceUacIsolation or ForceXXXConsole
Awaiting feedback mode: ON
from gsudo.
Matt, $inputObject
allows to do Get-Process notepad | Invoke-gsudo { Stop-Process }
. You will see it as $Input
inside the ScriptBlock since it is an automatic variable generated by Pwsh Invoke-Command.
Great catch it's causing the 'return' issue. Pushing a fix right now.
from gsudo.
I'm not able to distinguish between Terminating (Invoke-gsudo { throw}) and non-terminating errors ( Invoke-gsudo { Write-Error 1; Write-Error 2;}) here
and I think the ErrorAction needs to be Stop for the formers so they trigger catch blocks.
TIL: Apparently, nobody can. See PowerShell/PowerShell#3158
I would think we would let the users determine the
ErrorAction
flow within the[scriptblock]
passed intoInvoke-gsudo.ps1
? I would assume the aforementioned line should avoid declaring anErrorAction
and let the users$ErrorActionPreference
come into play.
I agree. I removed specifying the fixed ErrorAction you are referring to.
$Error.Exception.WasThrownFromThrowStatement
Thanks, that really helped. Now I do try/catch on the scriptblock to detect the terminating errors, and force throw $_
to ensure WasThrownFromThrowStatement
is true. Works 99% 🤷♂️.
Now, should I honor Invoke-gsudo -ErrorAction
parameter? Invoke-Command does not. No difference between:
- Invoke-Command { "/", "/nofound", "/" | Get-Item } -ErrorAction Stop
- Invoke-Command { "/", "/nofound", "/" | Get-Item }
It felt harmless to take the -ErrorAction
param (IF specified) and setting that as $ErrorActionPreference
in the elevated instance. Opinions?
If omitted the invokers ErrorActionPreference is forwarded to the elevated instance.
I may be confused with the use cases for the error handling.
Me too. I'm learning as I code here. Found this great recap on error handling on PS: See MicrosoftDocs/PowerShell-Docs#1583
I'd mimic Invoke-Command
assuming it's doing the proper thing, or what the user would expect, plus that is easier to communicate.
In a nutshell, keep the same exception type, keep the same stream. For example:
- Non-terminating errors:
- Should not terminate the pipeline execution.
- Capturable with
-ErrVarible
or2>&1
- E.g.
Invoke-gsudo { "\", "notExisting" | Get-Item } } -errVariable failed
- Terminating errors
- Capturable with try/catch
try { Invoke-Gsudo { throw; } } catch {"Catched: $_"}
Now, I still have problems between Script-terminating errors and Statement-terminating errors.
Apparently surrounding the script in a try/catch turns a Statement-terminating error into a Script-terminating error (in this context, actually into a scriptblock-terminating).
For example, Invoke-Command behaves differently surrounded by try/catch:
PS C:\Users\gerar> Invoke-Command { Some-InvalidCmdLet ; 10 }
Some-InvalidCmdLet: The term 'Some-InvalidCmdLet' is not recognized as a name of a cmdlet, function, script file, or executable program.
10
PS C:\Users\gerar> try { Invoke-Command { Some-InvalidCmdLet ; 10 } } catch { "Catched: $_" }
Catched: The term 'Some-InvalidCmdLet' is not recognized as a name of a cmdlet, function, script file, or executable program.
The later stops execution at Some-InvalidCmdLet
and never returns 10
.
The problem here is that I use try catch to detect termining errors.
So, is it correct to conclude that all statement-terminating errors will turn into script-terminating?
I was playing with the below.
Invoke-gsudo.ps1 { write-error 1; write-error 2; 2 }I would expect it to return
Invoke-gsudo.ps1: 1 Invoke-gsudo.ps1: 2 2Currently it is returning
2 Invoke-gsudo.ps1: 1I guess it is because of the redirection (
2>&1
) changing the order of the errors and then theErrorAction
on the aforementioned line.
Yes, the redirection changes the output order. No workaround AFAIK.
Also, the second exception was lost. Should be fixed now.
Here are a few test cases. Ideally each pair of lines should behave the same, but they don't. (Invoke-Command vs Invoke-gsudo).
Proper PS tests may exists in the future, for now a comment will do.
try { invoke-gsudo { 0/0 } } catch { "catched: $_" }
try { Invoke-Command { 0/0 } } catch { "catched: $_" }
Invoke-gsudo { 0/0;0/0 } # fail: only 1 exception, caused by try/catch
Invoke-Command { 0/0;0/0 }
try { invoke-gsudo { "asd" | ConvertFrom-Json } } catch { "catched: $_" }
try { Invoke-Command { "asd" | ConvertFrom-Json } } catch { "catched: $_" } # Weird, why catched? Oh.. PowerShell/PowerShell#2860
try { Invoke-Command { throw } } catch { "catched: $_" }
try { invoke-gsudo { throw } } catch { "catched: $_" }
try { invoke-Command { "notfound" | Get-Item } } catch { "catched: $_" }
try { invoke-gsudo { "notfound" | Get-Item } } catch { "catched: $_" }
try { invoke-Command { "notfound" | Get-Item -ErrorAction Stop } } catch { "catched: $_" }
try { invoke-gsudo { "notfound" | Get-Item -ErrorAction Stop } } catch { "catched: $_" }
try { invoke-Command { ".", "notfound" | Get-Item -ErrorAction Stop } } catch { "catched: $_" }
try { invoke-gsudo { ".", "notfound" | Get-Item -ErrorAction Stop } } catch { "catched: $_" }
#weird fail. Also, run as admin
try { invoke-command { Get-Service "netlogon" | Suspend-Service -ErrorAction Stop } } catch { "catched: $_" }
try { invoke-gsudo { Get-Service "netlogon" | Suspend-Service -ErrorAction Stop } } catch { "catched: $_" }
try { invoke-Command { Get-InvalidCmdLet ; 1 } } catch { "catched: $_" }
try { invoke-gsudo { Get-InvalidCmdLet ; 1 } } catch { "catched: $_" }
try { invoke-gsudo { [int]::Parse('foo') } } catch { "e $_" }
try { invoke-command { [int]::Parse('foo') } } catch { "e $_" }
I've just pushed a new version. Feedback welcomed!
from gsudo.
Uploaded tests, and bugfixing.
PS C:\git\gsudo> Invoke-Pester -Output Detailed
Pester v5.3.1
Starting discovery in 2 files.
Discovery found 16 tests in 205ms.
Running tests.
Running tests from 'C:\git\gsudo\src\gsudo.extras\gsudo.Tests.ps1'
Describing PS Gsudo (v7.2.1)
[+] It serializes return values as string. 2.33s (2.3s|38ms)
[+] When invoked as gsudo !!, It elevates the last command executed 452ms (451ms|1ms)
Running tests from 'C:\git\gsudo\src\gsudo.extras\Invoke-gsudo.Tests.ps1'
Describing PS Invoke-Gsudo (v7.2.1)
[+] It serializes return values maintaining its type 569ms (568ms|1ms)
[+] It serializes return values mantaining its properties. 503ms (502ms|1ms)
[+] It returns an array of values mantaining its properties. 524ms (523ms|1ms)
[+] It accepts objects from the pipeline. 482ms (480ms|2ms)
[+] It throws when Error thrown 622ms (621ms|1ms)
[+] It throws with expression runtime errors 1.14s (1.14s|1ms)
[+] It throws with .Net Exceptions 577ms (577ms|1ms)
[+] It throws when ErrorAction = Stop 570ms (570ms|1ms)
[+] It throws when ErrorActionPreference = Stop 550ms (550ms|0ms)
[+] It forwards ErrorActionPreference 'Stop' to the elevated instance 527ms (525ms|2ms)
[+] It forwards ErrorActionPreference 'Continue' to the elevated instance 498ms (498ms|1ms)
[+] It forwards ErrorActionPreference 'Ignore' to the elevated instance 494ms (493ms|1ms)
[+] It doesn't throw when ErrorActionPreference = Continue 1.23s (1.23s|1ms)
[+] It doesn't throw with '-ErrorAction Continue-' 2.69s (2.69s|1ms)
Tests completed in 49.29s
Tests Passed: 16, Failed: 0, Skipped: 0 NotRun: 0
Also on the build server: CI test results with inconvenient ordering.
And last, but not least: I added a gsudo PowerShell Module: (Add Import-Module pathto/gsudoModule.psm1
to your $PROFILE
) which adds support for gsudo !!
too. (As requested in #44)
from gsudo.
Released in v1.1.0
from gsudo.
There isn't really a good reason to write a native (i.e. C# compiled) wrapper cmdlet as far as I can see? If you want to marshal parameters using powershell's binder to gsudo's, a wrapper function would do the trick. Or perhaps you're not aware that cmdlet infers compiled code, and function infers script?
from gsudo.
Oh, I didn't mean a native c# cmdlet, but a function script.
My intent is just to add one Invoke-gsudo.ps1
file side by side with gsudo.exe
, both in the PATH.
Then you could Invoke-gsudo -ScriptBlock { Do-ElevatedStuff }
or whatever syntax is more welcomed for PS developers than the current (quote-escaping-hell) syntax...
from gsudo.
That's right. gsudo.exe does very little to support elevating PS commands. The trick is that it is the user's responsibility to generate a string with a valid PS command (hence the quoting-hell) and then, when gsudo detects it's being called from PS, it elevates the same PowerShell.exe with -c {command}
.
This can be seen with the --debug parameter:
PS $ gsudo "(Get-FileHash \""$file\"" -Algorithm $algorithm).Hash"
... executes gsudo "(Get-FileHash \"C:\test\test.txt\" -Algorithm MD5).Hash"
which then calls pwsh again:
Debug: Command to run: "C:\Users\ggrignoli\scoop\apps\pwsh\current\pwsh.exe" -NoLogo -NoProfile -Command "(Get-FileHash \"C:\test\test.txt\" -Algorithm MD5).Hash"
(...)
79F1F6A36DBEBF6888E9E1717766F5A6
In that model, the user should be aware that there is no object marshalling, only strings in and out. In the example you can capture the result because .Hash
returns a simple string, but good luck if it were a complex object.
So, what's next? The point of this issue is that I am open to suggestions and gather info on how far we can go.
Trying to pretend that a scriptblock is in the same lexical scope
It should be clear from the ground up that its not. There is a process-hop between elevated an unelevated instances so there will be serializing and deserializing of objects.
What is PS-Remoting doing with both local and remote scopes? Can we mimic that?
Take a look at this, it serializes a scriptblock while allowing the $using:LocalVariable
syntax: it substitutes from
i.e. Write-Host $a
becomes
Write-Host $([System.Management.Automation.PSSerializer]::Deserialize('<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell /2004/04">_x000D__x000A_ <S>HELLO</S>_x000D__x000A_</Objs>'))
AFAIK this would allow this syntax: Elevate-Command -ScriptBlock { $using:localVar + $remoteVar }
, unless I am missing something.
Serialization will produce huge strings, but we can use pwsh -c -
and then send the scriptblock via StdIn.
The output should be serialized before going to StdOut, then deserialized as well.
from gsudo.
New version (same link), supports -ArgumentList
and pipe input is received via $Input.
$local = "outside scope"
"TestString" | Elevate-Command -ScriptBlock {
$local = "inner scope"
Write-Host "Am I elevated? $([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match 'S-1-5-32-544'))"
Write-Host "Inner scope value: $local"
Write-Host "Outer scope value: $using:local"
Write-Host "Received Args: $args"
Write-Host "Pipeline Input: $Input"
} -ArgumentList 1, 2, 3
returns
Am I elevated? True
Inner scope value: inner scope
Outer scope value: outside scope
Received Args: 1 2 3
Pipeline Input: TestString
I've tried to make Elevate-Command
equivalent to Invoke-Command
, except that the latter does not supports $using:
syntax on localhost
.
Does it sound practical? What could be improved? Opinions?
Now I've been looking at Ìnvoke-Expression
... I am the exploring the idea of providing an Elevate-Expression
function. I guess it will look similar to gsudo
right now, but with a few differences:
- Quoting rules would be exactly PS rules, not subtle differences like " => \""
- Support
$using:
which will work by serializing the object using PSSerializer.
Any feedback at this early stage is highly welcome.
from gsudo.
I was playing around with the new build. I couldn't understand the piped $InputObject
piece. When I removed it, code like the below worked.
Invoke-gsudo -ScriptBlock { Get-Content .\readline.ps1 } -NoElevate
gsudo/src/gsudo.extras/Invoke-gsudo.ps1
Line 110 in e9ad64b
Some of this may feed into the I see now, I didn't know about the $Input
variable not being defined. Should $Input
be $InputObject
?$Input
automatic variable.
gsudo/src/gsudo.extras/Invoke-gsudo.ps1
Line 95 in e9ad64b
When I changed the above line to $InputObject
, I received the below error.
ErrorRecord : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and
its properties do not match any of the parameters that take pipeline input.
WasThrownFromThrowStatement : False
TargetSite : System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject] Invoke(System.Collections.IEnumerable)
Message : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The input object
cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties
do not match any of the parameters that take pipeline input.
Data : {System.Management.Automation.Interpreter.InterpretedFrameInfo}
InnerException :
HelpLink :
Source : System.Management.Automation
HResult : -2146233087
StackTrace : at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
at Microsoft.PowerShell.Executor.ExecuteCommandHelper(Pipeline tempPipeline, Exception& exceptionThrown, ExecutionOptions options)
from gsudo.
I'm not able to distinguish between Terminating (Invoke-gsudo { throw}) and non-terminating errors ( Invoke-gsudo { Write-Error 1; Write-Error 2;}) here
and I think the ErrorAction needs to be Stop for the formers so they trigger catch blocks.
I would think we would let the users determine the ErrorAction
flow within the [scriptblock]
passed into Invoke-gsudo.ps1
? I would assume the aforementioned line should avoid declaring an ErrorAction
and let the users $ErrorActionPreference
come into play.
As far as telling the difference between the errors, I was reading this and this. Maybe we can use one of these:
$Error.CategoryInfo.Category
$Error.Exception.WasThrownFromThrowStatement
Category
appears to always be OperationStopped
due to a System.Management.Automation.PipelineStoppedException
being called by ThrowTerminatingError(ErrorRecord)
. This is opposed to a non-terminating error which calls System.Management.Automation.Cmdlet.WriteError
. Not sure if we need to tell a difference between Write-Error 1
and Write-Error 1 -ErrorAction Stop
?
I may be confused with the use cases for the error handling. I was playing with the below.
Invoke-gsudo.ps1 { write-error 1; write-error 2; 2 }
I would expect it to return
Invoke-gsudo.ps1: 1
Invoke-gsudo.ps1: 2
2
Currently it is returning
2
Invoke-gsudo.ps1: 1
I guess it is because of the redirection ( 2>&1
) changing the order of the errors and then the ErrorAction
on the aforementioned line.
As another example, I was playing with the below which does work as I would expect.
Invoke-gsudo.ps1 { throw 'hello world'; 2 }
from gsudo.
Related Issues (20)
- Feature Request: Root-Like Mode (unsecure mode) HOT 3
- Issue: Multiple simultaneous gsudo versions throw "Unauthorized. (Different gsudo.exe?)"
- Feature Request: Make sudo more powerful HOT 1
- Issue: Nano and vim executables get stuck when opened with gsudo on cmd HOT 5
- Issue: gsudo: "Error: Invalid option: -noninteractive". The gsudo scriptblocks also fail. HOT 5
- Feature Request: Add '#' to lines in elevated shell process? (to mimic Linux) HOT 2
- Issue: System.NullReferenceException thrown at gsudo start HOT 1
- Issue: Wrong SID when using cached token HOT 1
- Feature Request: Hide console when running outside a terminal HOT 7
- Issue: sudo alias (sudo !!) throws a ParseError exception and doesn't elevate the last executed command in PowerShell Core HOT 3
- Feature Request: Give users a lecture when they use gsudo. HOT 5
- Error: `System.InvalidOperationException: No process is associated with this object` when using gsudo with Admin by Request HOT 2
- WSL wrapper will not work if gsudo is on different drive
- Issue: `gsudo` script fails missing `gsudo.exe` in MSYS env HOT 2
- Error: `ParentContainsErrorRecordException` when using `gsudo { Get-NetIPAddress }` HOT 4
- Tokenlist
- Issue: Windows 24H2 Has Sudo HOT 2
- Issue: Sophos AV blocks gsudo
- Issue: caching with `CacheMode = "Auto"` expires too soon in MSYS2 and Cygwin HOT 4
- Commands with Bool ($True/$False) Paramiters do not run within a gsudo session HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gsudo.