Golang calls windows.CreateProcessAsUser function how to get Stdout content:
func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error)
I tried to convert the C code of Creating a Child Process with Redirected Input and Output to Go code, but failed.
Related
log.New(os.Stdin, "in", 1).Println("TT")
The following code out stream looks like it should use stdout or stderr, but I'm using the stdin input stream.
It should go into some panic, but output to the console normally.
Why is this working fine?
I don't know why.
um Isn't stream input used to type on the keyboard? But since I input stream input to output, I don't think this should work. stdout:console,
stderr:console,
stdin:keyboard
TL;DR - From the source code:
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
Stdin, Stdout, and Stderr are open Files pointing to the standard
input, standard output, and standard error file descriptors.
what this actually means is that Go treats Stdin, Stdout and Stderr the same, just as regular Files. and why shouldn't it? that's really just what they are. If you run echo sometext > /dev/stdin in your shell of choice, you'll see that this is valid and the text "sometext" will be printed to the terminal
Digging Deeper
Let's examine the log.New function declaration:
func New(out io.Writer, prefix string, flag int) *Logger
New creates a new Logger. The out variable sets the destination to
which log data will be written. The prefix appears at the beginning of
each generated log line, or after the log header if the Lmsgprefix
flag is provided. The flag argument defines the logging properties.
You can see that the first argument is the io.Writer interface - which is declared as :
type Writer interface {
Write(p []byte) (n int, err error)
}
This effectively means that log.New accepts every struct that has a Write(p []byte) (n int, err error) method. And because os.Stdin is of type os.File, it matches the io.Writer interface specification and the signature of log.New.
I've just recently started working with Go, and I've run into some
behavior working with Cobra and Viper that I'm not sure I understand.
This is a slightly modified version of the sample code you get by
running cobra init. In main.go I have:
package main
import (
"github.com/larsks/example/cmd"
"github.com/spf13/cobra"
)
func main() {
rootCmd := cmd.NewCmdRoot()
cobra.CheckErr(rootCmd.Execute())
}
In cmd/root.go I have:
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var cfgFile string
func NewCmdRoot() *cobra.Command {
config := viper.New()
var cmd = &cobra.Command{
Use: "example",
Short: "A brief description of your application",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
initConfig(cmd, config)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("This is a test\n")
},
}
cmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.example.yaml)")
cmd.PersistentFlags().String("name", "", "a name")
// *** If I move this to the top of initConfig
// *** the code runs correctly.
config.BindPFlag("name", cmd.Flags().Lookup("name"))
return cmd
}
func initConfig(cmd *cobra.Command, config *viper.Viper) {
if cfgFile != "" {
// Use config file from the flag.
config.SetConfigFile(cfgFile)
} else {
config.AddConfigPath(".")
config.SetConfigName(".example")
}
config.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := config.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", config.ConfigFileUsed())
}
// *** This line triggers a nil pointer reference.
fmt.Printf("name is %s\n", config.GetString("name"))
}
This code will panic with a nil pointer reference at the final call to
fmt.Printf:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x50 pc=0x6a90e5]
If I move the call to config.BindPFlag from the NewCmdRoot
function to the top of the initConfig command, everything runs
without a problem.
What's going on here? According to the Viper docs regarding the use of
BindPFlags:
Like BindEnv, the value is not set when the binding method is
called, but when it is accessed. This means you can bind as early as
you want, even in an init() function.
That's almost exactly what I'm doing here. At the time I call
config.BindPflag, config is non-nil, cmd is non-nil, and the
name argument has been registered.
I assume there's something going on with my use of config in a
closure in PersistentPreRun, but I don't know exactly why that is
causing this failure.
I thought this was interesting so I did some digging and found your exact problem documented in an issue. The problematic line is this:
config.BindPFlag("name", cmd.Flags().Lookup("name"))
// ^^^^^^^
You created a persistent flag, but bound the flag to the Flags property. If you change your code to bind to PersistentFlags, everything will work as intended even with this line in NewCmdRoot:
config.BindPFlag("name", cmd.PersistentFlags().Lookup("name"))
I don't have any issue if I use cmd.PersistentFlags().Lookup("name").
// *** If I move this to the top of initConfig
// *** the code runs correctly.
pflag := cmd.PersistentFlags().Lookup("name")
config.BindPFlag("name", pflag)
Considering you just registered persistent flags (flag will be available to the command it's assigned to as well as every command under that command), it is safer to call cmd.PersistentFlags().Lookup("name"), rather than cmd.Flags().Lookup("name").
The latter returns nil, since the PersistentPreRun is only called when rootCmd.Execute() is called, which is after cmd.NewCmdRoot().
At cmd.NewCmdRoot() levels, flags have not yet been initialized, even after some were declared "persistent".
This ends up being a little more complex than it might appear at first glance, so while the other answers here helped me resolve the problem I'd like to add a little detail.
There are some nuances in the documentation that aren't particularly clear if you're just starting to work with Cobra. Let's start with the documentation for the PersistentFlags method:
PersistentFlags returns the persistent FlagSet specifically set in the current command.
The key is in ...in the current command. In my NewCmdRoot root method, we can use cmd.PersistentFlags() because the root command is the current command. We can even use cmd.PersistentFlags() in the PersistentPreRun method, as long as we're not processing a subcommand.
If we were to re-write cmd/root.go from the example so that it includes a subcommand, like this...
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var cfgFile string
func NewCmdSubcommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "subcommand",
Short: "An example subcommand",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("This is an example subcommand\n")
},
}
return cmd
}
func NewCmdRoot() *cobra.Command {
config := viper.New()
var cmd = &cobra.Command{
Use: "example",
Short: "A brief description of your application",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
initConfig(cmd, config)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Hello, world\n")
},
}
cmd.PersistentFlags().StringVar(
&cfgFile, "config", "", "config file (default is $HOME/.example.yaml)")
cmd.PersistentFlags().String("name", "", "a name")
cmd.AddCommand(NewCmdSubcommand())
err := config.BindPFlag("name", cmd.PersistentFlags().Lookup("name"))
if err != nil {
panic(err)
}
return cmd
}
func initConfig(cmd *cobra.Command, config *viper.Viper) {
name, err := cmd.PersistentFlags().GetString("name")
if err != nil {
panic(err)
}
fmt.Printf("name = %s\n", name)
if cfgFile != "" {
// Use config file from the flag.
config.SetConfigFile(cfgFile)
} else {
config.AddConfigPath(".")
config.SetConfigName(".example")
}
config.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := config.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", config.ConfigFileUsed())
}
// *** This line triggers a nil pointer reference.
fmt.Printf("name is %s\n", config.GetString("name"))
}
...we would find that it works when executing the root command:
$ ./example
name =
name is
Hello, world
But it fails when we run the subcommand:
[lars#madhatter go]$ ./example subcommand
panic: flag accessed but not defined: name
goroutine 1 [running]:
example/cmd.initConfig(0xc000172000, 0xc0001227e0)
/home/lars/tmp/go/cmd/root.go:55 +0x368
example/cmd.NewCmdRoot.func1(0xc000172000, 0x96eca0, 0x0, 0x0)
/home/lars/tmp/go/cmd/root.go:32 +0x34
github.com/spf13/cobra.(*Command).execute(0xc000172000, 0x96eca0, 0x0, 0x0, 0xc000172000, 0x96eca0)
/home/lars/go/pkg/mod/github.com/spf13/cobra#v1.1.3/command.go:836 +0x231
github.com/spf13/cobra.(*Command).ExecuteC(0xc00011db80, 0x0, 0xffffffff, 0xc0000240b8)
/home/lars/go/pkg/mod/github.com/spf13/cobra#v1.1.3/command.go:960 +0x375
github.com/spf13/cobra.(*Command).Execute(...)
/home/lars/go/pkg/mod/github.com/spf13/cobra#v1.1.3/command.go:897
main.main()
/home/lars/tmp/go/main.go:11 +0x2a
This is because the subcommand inherits the PersistentPreRun command from the root (this is what the Persistent part means), but when this method runs, the cmd argument passwd to PersistentPreRun is no longer the root command; it's the subcommand command. When we try to call cmd.PersistentFlags(), it fails because the current command doesn't have any persistent flags associated with it.
In this case, we need to instead use the Flags method:
Flags returns the complete FlagSet that applies to this command (local and persistent declared here and by all parents).
This gives us access to persistent flags declared by parents.
An additional issue, that doesn't appear to be called out explicitly in the documentation, is that Flags() is only available after command processing has been run (that is, after you call cmd.Execute() on the command or a parent). That means we can use it in PersistentPreRun, but we can't use it in NewCmdRoot (because that method finishes before we process the command line).
TL;DR
We have to use cmd.PersistentFlags() in NewCmdRoot because we're looking for persistent flags applied to the current command, and the value from Flags() won't be available yet.
We need to use cmd.Flags() in PersistentPreRun (and other persistent commands methods) because when processing a subcommand, PersistentFlags will only look for persistent flags on the current command, but won't traverse parents. We need to use cmd.Flags() instead, which will roll up persistent flags declared by parents.
I wanna make push subscription to Windows Event Log in Golang
How exactly should I pass a callback function?
EVT_SUBSCRIBE_CALLBACK is the pointer of function, like
typedef DWORD ( WINAPI *EVT_SUBSCRIBE_CALLBACK)(
EVT_SUBSCRIBE_NOTIFY_ACTION Action,
PVOID UserContext,
EVT_HANDLE Event
);
So, my variant looks like this:
func logCallback() syscall.Handle {
cb := func(_ uintptr, _ uintptr, _ uintptr) uint64 {
fmt.Printf("callback called %v", data)
return 0
}
ptr := syscall.NewCallback(cb)
return syscall.Handle(ptr) // type syscall.Handle uintptr
}
I get successfully subscribed handler with no errors, but it still doesn't work.
Any ideas why? Where should I look first?
When using syscall make sure the to include import "C" at the top of your file. Glad it helped you.
I'm implementing a wrapper around the standard log package to make a logger with various log levels.
I have the following interface:
type Logger interface {
Trace(fmt string, args ...interface{})
Debug(fmt string, args ...interface{})
Info(fmt string, args ...interface{})
Warn(fmt string, args ...interface{})
Error(fmt string, args ...interface{})
Fatal(fmt string, args ...interface{})
Panic(fmt string, args ...interface{})
}
In the implementation I have something like this (not the exact code)
func Info(format string, args ...interface{}){
msg := fmt.Sprintf(format, args...)
log.Println(msg)
}
Now, assume I call my library like this:
logger.Info("Hello %s", "World")
I get the printout: "Hello %!(EXTRA string=WORLD)", instead of the expected "Hello World". There a similar output if I do
msg := fmt.Sprintf(format, args)
This returns "Hello World%!EXTRA []interface{}=[]".
I can't reproduce this behavior. Are you sure it's not a simple error that you forgot to show here?
https://play.golang.org/p/-jtmll17Xj
package main
import "fmt"
func Info(format string, args ...interface{}){
msg := fmt.Sprintf(format, args...)
fmt.Print(msg)
}
func main() {
Info("Hello %s", "World")
}
Prints
Hello World
According to the fmt docs, %!(EXTRA string=WORLD) is added to the string when you pass extra parameters, unexpected by the format. Maybe you are using the format string "Hello World" instead of "Hello %s", or passing the argument twice?
The error was between the chair and keyboard. I mixed up the following interfaces:
func Print(v ...interface{})
func Printf(format string, v ...interface{})
Some of my code was calling the library without a format string.See here for a more detailed example: http://play.golang.org/p/Xx79qujaFp
Happens aswell when your message has no verbs and the varargs are empty but coming from elsewhere:
func CustomPrintf(message string, a ...interface{}) {
fmt.Printf(message, a) // for no verbs in message you'll get this "EXTRA" suffix
}
That's a special case of a general error. You've got to spread a first. So use fmt.Printf(message, a...) to make it to varags again.
This can happen if you pass nil params to your format, for instance:
myStr := fmt.Sprintf("check/%s", "hello", nil)
will set the value of myStr to: "check/hello%!"
In this example the extra params was the third param with nil value.
so make sure to remove any extra params.
Also, happens due to a simple (typo?) if you forget/miss putting in the "%".
e.g.
fmt.Printf("v\n", myvar)
instead of
fmt.Printf("%v\n", myvar)
obviously not a "syntax" error, so nothing for the compiler to catch.
I realize this nets out to the same as some of the other answers, but I think this is clearer and (maybe?) the most common cause.
I have a function func more(... t). I'm wondering if it's possible to use a slice to populate a list of arguments ... .
I'm trying to solve the following program. Basically to mimic a normal shell which receives the command as a string.
Command function requires a "list" of arguments and I don't see how I can convert a string into a such list
import "os/exec"
import "strings"
func main(){
plainCommand := "echo hello world"
sliceA := strings.Fields(plainCommand)
cmd := exec.Command(sliceA)
}
The Go Programming Language Specification
Passing arguments to ... parameters
If f is variadic with final parameter type ...T, then within the
function the argument is equivalent to a parameter of type []T. At
each call of f, the argument passed to the final parameter is a new
slice of type []T whose successive elements are the actual arguments,
which all must be assignable to the type T. The length of the slice is
therefore the number of arguments bound to the final parameter and may
differ for each call site.
Package exec
func Command
func Command(name string, arg ...string) *Cmd
Command returns the Cmd struct to execute the named program with the
given arguments.
The returned Cmd's Args field is constructed from the command name
followed by the elements of arg, so arg should not include the command
name itself. For example, Command("echo", "hello")
For example,
package main
import (
"fmt"
"os/exec"
)
func main() {
name := "echo"
args := []string{"hello", "world"}
cmd := exec.Command(name, args...)
out, err := cmd.Output()
if err != nil {
fmt.Println(err)
}
fmt.Println(string(out))
}
Output:
hello world
A list of command arguments can be retrieved from the flag package Args() function. You can then pass this to a function using the variadic input style (func(input...))
From the Spec:
If f is variadic with final parameter type ...T, then within the function the argument is equivalent to a parameter of type []T. At each call of f, the argument passed to the final parameter is a new slice of type []T whose successive elements are the actual arguments, which all must be assignable to the type T.
Example:
package main
import "fmt"
func echo(strings ...string) {
for _, s := range strings {
fmt.Println(s)
}
}
func main() {
strings := []string{"a", "b", "c"}
echo(strings...) // Treat input to function as variadic
}
See The Go spec for more details.
Playground
func Command
func Command(name string, arg ...string) *Cmd
Command returns the Cmd struct to execute the named program with the given arguments.
So you have to extract the command which is found at sliceA[0] and then pass all the arguments with a variadic but removing the command sliceA[1:]....
import "os/exec"
import "strings"
func main(){
plainCommand := "echo hello world"
sliceA := strings.Fields(plainCommand)
cmd := exec.Command(sliceA[0], sliceA[1:]...)
}