Showing posts with label go. Show all posts
Showing posts with label go. Show all posts

Friday, September 6, 2024

Wallpaper

 I just published small Go  project on GitHub:

https://github.com/jumbleview/decor

This is the program which takes jpeg picture as argument and set it as Windows desktop background.

Command line looks like this:

  • decor.exe [-s] path_to_jpeg_file
It starts with single argument: path to jpeg file. If before an argument there is the flag -s program starts in silent mode (without console).

Program reads jpeg file, encodes it, crops image so it's width-to-height ratio matches width-to-height ratio of computer monitor, saves the image as bmp file and sets it as a screen background.

It is pure Go program. It should be compiled with command

  • go build -ldflags -H=windowsgui 

  • Using such flags allows to start without Windows console attached. Console is created dynamically or suppressed by flag -s.

    This program allows to change background by desktop shortcut, batch file or schedule background change with Task scheduler.

    Update on September 13, 2024.

    One more project on GitHub:

    It is more advanced version of background utility.  It starts with such  command:
    • picshuffle.exe [-s] [-l] path_to_folder_or_jpeg_file

    If argument is a path to a jpeg file program  works exactly as decor.exe.   

    In case argument is a path to a directory with some jpeg files program reads content of directory and randomly picks one file from that directory to set it as a desktop background. Program tracks selected files in storage picshuffle.db so once selected file will not be selected again till all files from this directory are taken.
    I personally use this program out of Windows task scheduler at logon event. Each time after a logon into the system  I see different background picture.

    To track selected files program uses embedded key-value store  bolt  (go.etcd.io/bbolt). If started with flag [-l] program prints list of files used as a background within last 365 days.




      Monday, June 24, 2024

      Four Years in Use

       Four years ago I published post about my Go terminal application which I use as  personal password manager.

      https://www.jumbleview.info/2020/04/here-we-go.html

      During all these years I used it on constant basis making some tweaking here and there. This post  summarizes major changes.


      • Application now supports mouse interface. User can utilize keyboard  hits  and mouse clicks interchangeably.
      • At start application can be supplied with some flags. That allows  to select application colors, initial application mode, even  add new table column or delete existing one.
      • In case current cell contains valid URL user can open browser window on that URL with the help of WWW button.
      • There is no button Add anymore (its functionality  absorbed  by button Edit). 
      • When table is in focus user may select  row by hitting key which corresponds to the first letter of the  record name. 
      • Initial implementation had a security vulnerability: content of clipboard was not cleared  in case application was terminated  by closing console window .  Now it is fixed: disregarding of which  way application is terminated (by Ctrl+C, Exit button, or window closing)  clipboard is empty.
      Source code of the application  as well as readme is available to the public (same place)     https://github.com/jumbleview/tspur

      Saturday, April 4, 2020

      Here We Go


      For a long time, I wanted to have an application to keep my personal data in place. My requirements were next:


      • It should be lightweight and minimalistic.
      • It must present protected (hidden) and open (visible) data in the single set.
      • It should make the process of data input/edition easy, but still protects this data from an accidental unintentional change.
      And here let me show you the one which I eventually built.



      This application is written in Go. It is not a real Windows GUI but rather TUI and it uses an excellent Go package "rivo/tview" as the foundation. It looks and feels less like modern Windows commercial programs, but more like old fashioned PC Dos application.  Still, it does whatever expected in an efficient and straightforward way.

      The terminal screen consists of two areas:

      • Top menu
      • Table with User Records

      The application starts with a single argument: the path to the file with data storage. Storage is encoded and password protected. If such storage does not exist, the application will ask you to enter the new password and will create new storage.
      At the start, the application puts focus on the top menu. Hitting "Enter", while button "Select" is in focus, move the focus to the table. To put the focus back on the top menu use "Esc".To navigate through the menu or the table user must use arrow keys.
      Numbers of table rows and columns are unlimited but it is unlikely somebody will use more than a hundred rows or more than 3..5 columns. Each rows contains one cell (Record Name), which is always visible, and several values. Values on each row may be either all visible or all hidden.
      The application supports four modes:


      • Clipboard-on-Enter. If the user hits "Enter" on the selected cell its content is copied into the clipboard.
      • Clipboard-on-Select. During navigation content of the selected cell is copied into the clipboard.
      • Visible-on-Enter. If the user hits "Enter" on the selected cell with hidden content it becomes visible. When the cell becomes unselected its content becomes hidden again.
      • Visible-on-Select. If the user selects the cell with hidden content it becomes visible. When the cell becomes unselected its content becomes hidden again.
      The user may add new records (button "Add") or edit existing (button "Edit"). To edit existing record select record on the table, then by "Esc" go to the top menu and hit button "Edit". The record may be extended with one extra value. If there is a need to add several extra values repeat the process several times. The short clip below illustrates how the program works.




      Source code is available  https://github.com/jumbleview/tspur . The project "readme" contains some additional details regarding its dependencies, platform support, how to build it and run the demo. If you will find the approach useful feel free to take this application as is or use it as a starting point for your own project.

      Update 4/29/20. Optional and limited support of Git added to the project.

      It would be not wise to keep a file with data only locally. Keeping it somewhere on remote storage provides data reliability and the ability to access it from different computers. Git repository looks like the obvious choice. It is assumed that a user will create a private repository with some Git provider and clone it locally. If "tspur" sees that data storage is located on the directory with working git tree it adds button "Git" to the top menu. That button may trigger a chain of git operations, namely: stages file with data, commits it, and pushes it to the remote. 


      June 2024 update.  I published post about  current application state https://www.jumbleview.info/2024/06/four-years-in-usage.html

      Saturday, September 3, 2016

      Windows Console on Demand in Go

      There are two kinds of Windows programs: Windows GUI or Console Application. There could be third case:  process, which does not have any visual representation at all and needs to be running in the background. For that case program maybe be built as Windows GUI, but it should not have any code, which creates Windows objects.  But what if  you want from application sometimes  to be silent and sometimes  to be verbose and to have a console. Possible use cases are:
      • Printing version of the utility if started with special flag (like -V)
      • Program needs complicated tune up through the  command line arguments or configuration file, but normally is  running on the background. It would be beneficially to have a choice either run it with console or run it quietly.
      That could be achieved by compiling application as Windows GUI and allocating  or attaching console to the process during run-time if needed. There are a lot of examples how to do that in C/C++. When I myself looked for the solution several years ago I have found this link  helpful. Fragment of the code, which creates console may look like this.

       // taken from: http://www.codeproject.com/KB/dialog/ConsoleAdapter.aspx
      
       AllocConsole();
       int fdout = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
       FILE* fout = _fdopen(fdout, "w");
       *stdout = *fout;
      
       int fdin = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
       FILE* fin = _fdopen(fdin, "r");
       *stdin = *fin;
      
      
      

      Nowadays I found myself  programming more and more in Go. While initially Go compiler was intended for Linux only,  that is not the case anymore. Windows now is the first class citizen in the Go world. Recently I needed to create application, which may open the console if that demanded by  command line argument, but work invisibly  otherwise . To my surprise there were not that many online information how to do that in Go. I did find one answered question in StackOverflow. Alas, proposed solution did not work for me out of the box. But using it as starting point and after some googling I have found workable solution. Here is sample of Go application, which will allocate console, print some prompt, wait for keyboard input and quit.

      // go build -ldflags -H=windowsgui
      package main
      
      import "fmt"
      import "os"
      import "syscall"
      
      func main() {
       modkernel32 := syscall.NewLazyDLL("kernel32.dll")
       procAllocConsole := modkernel32.NewProc("AllocConsole")
       r0, r1, err0 := syscall.Syscall(procAllocConsole.Addr(), 0, 0, 0, 0)
       if r0 == 0 { // Allocation failed, probably process already has a console
        fmt.Printf("Could not allocate console: %s. Check build flags..", err0)
        os.Exit(1)
       }
       hout, err1 := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
       hin, err2 := syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
       if err1 != nil || err2 != nil { // nowhere to print the error
        os.Exit(2)
       }
       os.Stdout = os.NewFile(uintptr(hout), "/dev/stdout")
       os.Stdin = os.NewFile(uintptr(hin), "/dev/stdin")
       fmt.Printf("Hello!\nResult of console allocation: ")
       fmt.Printf("r0=%d,r1=%d,err=%s\nFor Goodbye press Enter..", r0, r1, err0)
       var s string
       fmt.Scanln(&s)
       os.Exit(0)
      }
      
      I would like to point some details about syscall.Syscall invocation for AllocConsole :
      • This function  has five arguments. It is different of what you will find in the online Go Doc . Looks like doc references Linux definition, which is not the same as Windows.
      • Second parameter here is number of arguments in dll function. For our case it is 0.
      • Function returns three variables, but only first is really meaningful. It is the result returned by AllocConsole function. Second variables always 0. Third variables  is an  error, but in cannot be analyzed in the regular Go way as far as it is never nil.  Still it could be useful: in case of success its value is different from value on failure (for example if application was build with no windowsgui flag and already has the console ) .