Tag: Windows

  • When I was 16 years old or so, one day, my computer didn’t boot. I got a blue screen with some white text-mode error. Something was broken with the file system. This was after being utterly disappointed by Windows 95 and before I became a Linux person, so I was running Windows NT 4.0. I was the only person I knew running that operating system, and thus the only person I knew with an NTFS partition.

    What to do now? That was my only computer, thus I couldn’t get online, smartphones wouldn’t be invented for another decade, I had nobody to ask for help and no tools to run checks on an NTFS partition. That filesystem was quite new back then. I could just blank the hard drive and reinstall Windows NT and all the software. But what about my data? my data!!!

    At 16 years old I learned the lesson that the data is the most valuable and important thing inside my computer. Everything is replaceable. I’m sure if I could see that data now I would life, but for 16-year-old-me, that was my life. I started making backups and since that day I had a personal backup strategy that’s more robust than 90% of the companies I talk to. I have yet to lose a file and I hope to keep it that way. My ex-wife recently recovered from a complete computer failure because she’s following the backup strategy I set up for her.

    One of the things I wonder is, should I have to do a total restore of my data, how do I verify it? I have more than 2 million files. Big chunks could be missing and it might take me years to notice. Because I have so much data to backup, keeping my 3 backups all up to date is hard, so it’s possible that I may have to reconstruct my information piecing things together from the 3 of them. Technically my backup software should be able to do it. But… I’m skeptical.

    This is why every night I have an automatic script that generates a list of all of my files in a text file. That text file gets backed up and unless that files gets permanently and historically lost, I can use it to verify a backup restore. I think my friend Daniel Magliola gave me this idea.

    Since I use Windows (shocker, I know, but try building a Mac workstation with 6 screens and play video games and report back to me), I wrote the script in PowerShell, but since I couldn’t find anything like Linux’s find, the script invokes wsl. Here it is, normally I put it in c:\Users\pupeno\.bin\filelist.ps1:

    echo "Creating list of all files in C:"
    
    wsl find /mnt/c/Users/pupeno -type b,c,p,f,l,s > C:\Users\pupeno\.all-files.new.txt
    
    move -Force C:\Users\pupeno\.all-files.new.txt C:\Users\pupeno\.all-files.txt
    
    echo "Creating lists of all files in D:"
    
    wsl find /mnt/d -type b,c,p,f,l,s > D:\.all-files.new.txt
    
    move -Force D:\.all-files.new.txt D:\.all-files.txt
    
    echo "Creating lists of all files in E:"
    
    wsl find /mnt/e -type b,c,p,f,l,s > E:\.all-files.new.txt
    
    move -Force E:\.all-files.new.txt E:\.all-files.txt
    

    And this is how it’s configured in the Task Scheduler to run every night. First run Task Scheduler:

    Once it’s open, create a new task:

    I hope it helps.

  • Update 2018-05-23: Updated the code to my current version, which fixes a few bugs.

    When doing usability testing of an alpha version of Dashman, one thing that I was strongly asked was to have the windows remember their sizes when you re-open the application. The need was clear as it was annoying to have the window be a different size when re-started.

    The new version of Dashman is built using Java and JavaFX and thus I searched for how to do this, how to restore size. I found many posts, forums, questions, etc all with the same simplistic solution: restoring width and height, and maybe position.

    What those were missing was restoring whether the window was maximized (maximized is not the same as occupying all the available space, at least in Windows). But most important than that, none of the solutions took into consideration the fact that the resolutions and quantity of screens could be different than the last time the application run, thus, you could end up with a window completely out of bounds, invisible, immobile.

    I came up with this solution, a class that’s designed to be serializable to your config to store the values but also restore them and make sure the window is visible and if not, move it to a visible place:

    // Copyright (c) 2017-2018 Flexpoint Tech Ltd. All rights reserved.
    
    package tech.dashman.dashman;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import javafx.application.Platform;
    import javafx.geometry.Rectangle2D;
    import javafx.stage.Screen;
    import javafx.stage.Stage;
    import lombok.Data;
    import tech.dashman.common.Jsonable;
    
    @Data
    public class StageSizer implements Jsonable {
        private static double MINIMUM_VISIBLE_WIDTH = 100;
        private static double MINIMUM_VISIBLE_HEIGHT = 50;
        private static double MARGIN = 50;
        private static double DEFAULT_WIDTH = 800;
        private static double DEFAULT_HEIGHT = 600;
    
        private Boolean maximized = false;
        private Boolean hidden = false;
        private Double x = MARGIN;
        private Double y = MARGIN;
        private Double width = DEFAULT_WIDTH;
        private Double height = DEFAULT_HEIGHT;
    
        @JsonIgnore
        private Boolean hideable = true;
    
        @JsonIgnore
        public void setStage(Stage stage) {
            // First, restore the size and position of the stage.
            resizeAndPosition(stage, () -> {
                // If the stage is not visible in any of the current screens, relocate it to the primary screen.
                if (isWindowIsOutOfBounds(stage)) {
                    moveToPrimaryScreen(stage);
                }
                // And now watch the stage to keep the properties updated.
                watchStage(stage);
            });
        }
    
        private void resizeAndPosition(Stage stage, Runnable callback) {
            Platform.runLater(() -> {
                if (getHidden() != null && getHidden() && getHideable()) {
                    stage.hide();
                }
                if (getX() != null) {
                    stage.setX(getX());
                }
                if (getY() != null) {
                    stage.setY(getY());
                }
                if (getWidth() != null) {
                    stage.setWidth(getWidth());
                } else {
                    stage.setWidth(DEFAULT_WIDTH);
                }
                if (getHeight() != null) {
                    stage.setHeight(getHeight());
                } else {
                    stage.setHeight(DEFAULT_HEIGHT);
                }
                if (getMaximized() != null) {
                    stage.setMaximized(getMaximized());
                }
                if (getHidden() == null || !getHidden() || !getHideable()) {
                    stage.show();
                }
    
                new Thread(callback).start();
            });
        }
    
        public void setHidden(boolean value) {
            this.hidden = value;
        }
    
        private boolean isWindowIsOutOfBounds(Stage stage) {
            for (Screen screen : Screen.getScreens()) {
                Rectangle2D bounds = screen.getVisualBounds();
                if (stage.getX() + stage.getWidth() - MINIMUM_VISIBLE_WIDTH >= bounds.getMinX() &&
                    stage.getX() + MINIMUM_VISIBLE_WIDTH <= bounds.getMaxX() &&
                    bounds.getMinY() <= stage.getY() && // We want the title bar to always be visible.
                    stage.getY() + MINIMUM_VISIBLE_HEIGHT <= bounds.getMaxY()) {
                    return false;
                }
            }
            return true;
        }
    
        private void moveToPrimaryScreen(Stage stage) {
            Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
            stage.setX(bounds.getMinX() + MARGIN);
            stage.setY(bounds.getMinY() + MARGIN);
            stage.setWidth(DEFAULT_WIDTH);
            stage.setHeight(DEFAULT_HEIGHT);
        }
    
        private void watchStage(Stage stage) {
            // Get the current values.
            setX(stage.getX());
            setY(stage.getY());
            setWidth(stage.getWidth());
            setHeight(stage.getHeight());
            setMaximized(stage.isMaximized());
            setHidden(!stage.isShowing());
    
            // Watch for future changes.
            stage.xProperty().addListener((observable, old, x) -> setX((Double) x));
            stage.yProperty().addListener((observable, old, y) -> setY((Double) y));
            stage.widthProperty().addListener((observable, old, width) -> setWidth((Double) width));
            stage.heightProperty().addListener((observable, old, height) -> setHeight((Double) height));
            stage.maximizedProperty().addListener((observable, old, maximized) -> setMaximized(maximized));
            stage.showingProperty().addListener(observable -> setHidden(!stage.isShowing())); // Using an invalidation instead of a change listener due to this weird behaviour: https://stackoverflow.com/questions/50280052/property-not-calling-change-listener-unless-theres-an-invalidation-listener-as
        }
    }
    

    and the way you use it is quite simple. On your start method, you create or restore an instance of StageSizer and then do this:

    public void start(Stage stage) {
        StageSizer stageSizer = createOrRestoreStageSizerFromConfig();
        stageSizer.setStage(stage);
    }
    

    I haven’t put a lot of testing on this code yet but it seems to work. Well, at least on Windows. The problem is that this snippet is interacting with the reality of screen sizes, resolutions, adding and removing monitors, etc. If you find a bug, please, let me know and I might release this a library with the fix so we can keep on collectively improving this.

  • If I was in charge of GitHub, I would build a team of .NET Programmers and have them built an awesome UI for Git on Windows, bundle it with Git itself as well as other usually needed programs like an SSH client and release it for free. Well, as open source of course.

    The reason for that is that almost everybody that I know that’s using Git is also using GitHub and the number one objection I get to Git is Windows support. I myself chosen Mercurial once before just to be able to cooperate with my Windows-using friends. I think it’s time someone fixes that and I think GitHub has the most to win.

    I know Git can be installed on Windows and that it works. But you need more than that. You need on amazing user experience and Git on Windows doesn’t provide it.

    There are several reasons for that. Running Git in Windows is not as nice as Linux or Mac OS X, period. Even if the support was realyl good, the command line itself in Windows is not on par with Bash… even when you run Bash itself on Windows (which the last time I checked, you had to do to run Git).

    Most important than that is that the Windows crowd are just used to UIs, so the most amazing command line tool won’t stand a chance against the crappiest UI. Windows users just search for another tool when no UI is provided. Even myself when using Windows do that. It’s another world with another dynamic and you have to play by their rules to win their game. And I have to admit, if I had to stop using MacOSX I would miss my favorite Git UI a lot, GitX (L).

  • NetBeans could make the Ruby on Rails experience great for the vast majority of developers who are using Windows, where installing Ruby, Rails, PHP, MySQL, Python, etc is always a pain and the end result is ugly. But it falls short in some important ways which turned my experience with it into a nightmare.

    The reason I say “for developers using Windows” is because I believe that for everybody else, the experience is great already. Or as good as it can be and NetBeans can be an excellent IDE, but not improve the installation and managing experience.

    This is my story, my rant.

    I downloaded the latest NetBeans and installed it. When creating my first Ruby project, I encountered the first problem. Ruby chocked on my username, which was “J. Pablo Fernández”. You could say it was my fault. Windows 7 asked for my name and I typed it. I wasn’t aware it was asking for my username. Even then I would have typed the same, because Windows 7 doesn’t distinguish between usernames and names, and in the 21st century, computers should be able to deal with any character anywhere.

    I know it’s not NetBeans’ fault, it’s Ruby’s. But! Can you imagine a Software Engineer telling Steve Jobs “oh, copying files in a Mac behaves weirdly because it uses rsync and that’s its behavior, you see, it makes sense because…”? Of course Steve would have interrupted: “You’ve failed me for the last time”. The next developer would have patched rsync, trying to get the patch upstream, or creating an alternate rsync or stop using rsync.

    I’ve spent many hours creating another user, migrating to it, which in Windows is like 100 times harder than it should.

    Hours later, as soon as I created a project I got a message saying that I should upgrade gem, Ruby’s package manager, because the current version was incompatible with the current Rails version. By then I had already played with NetBeans’ gem interface telling it to upgrade everything, it should have upgraded gem as well, not just the gems. Every single developer out there running NetBeans must be encountering this error, and indeed there are quite a few threads about it on forums.

    Trying to upgrade gem with NetBeans was impossible. I think what they did to install and upgrade gems in NetBeans is excellent, but failing to upgrade gem itself was a huge drawback. This one was NetBeans’ fault. Neverfear, let’s do it from the command line.

    When doing it from the command line I encountered another error:

    \NetBeans was unexpected at this time.

    Looking around it seems it’s because of the spaces in “Program Files (x86)”. That means that the command line environment for Ruby that NetBeans installs is broken for everybody. I repeat: everybody. The answer: install it somewhere else.

    Well, I have two things to say about it: first, fix the freaking thing, Ruby, gem, whatever. Paths can have spaces and all kind of weirdness. It’s a big world full of people speaking languages that can’t be represented with ASCII and people that believe computers should do our bidding, instead of the other way around. “If I want spaces you better give me spaces, useless lump of metal and silicon”.

    Second, if you know one of your dependencies is broken, try to avoid triggering the broken behavior or at least warn the user about it. “We see you picked C:\Program Files (x86)\ to install NetBeans, which is pretty standard, but you know, Ruby is broken and can’t work in there, not even JRuby, so if you plan to use those at all, please consider installing it somewhere else.”

    I uninstalled NetBeans, or tried to. The uninstaller didn’t work. I deleted it and tried to install it on C:\ProgramFilesx86, which failed because some other directory created by NetBeans somewhere else existed from the previous installation, which halted the installation. I started a dance of run installer, remove dir, run installer, remove dir, run installer… until it worked.

    Once I finished I found out that NetBeans installed in C:\ProgramFilesx86\Netbeans 6.7.1. Yes, that’s a space. Oh my…

    As a bonus, NetBeans can’t automatically find Sun’s JDK in its default directory. I had to point to it by hand. Sun was, as usually, absolutely disrespectful of the platform conventions and installed its crap in C:\Sun. I would have picked another place but I thought “I’m sure some stupid program will want to pick that shit from there”. Silly me.

    12 hours have passed and I still haven’t been able to write a single line of source code. I contemplated installing Ruby by hand, but it’s so ugly that I decided I’m not going to use Windows for this. I’m going to work on another platform where installing Ruby is trivial and where I would probably never touch NetBeans because I have other editors.

    I know there’s a lot not really related to NetBeans here, for example, the fact that working with Python, or Ruby or MySQL in Windows is a pain; but it’s a great opportunity for NetBeans. There are developers wanting to use those languages and environments and if NetBeans makes it easy for them, they will pick NetBeans not because of its editor, but because of everything else (which is what I was hoping to get out of NetBeans).

    Aside from doing some usability tests, the people working on NetBeans should learn from the people working on Ubuntu (not the people working on Evolution) and instead of asking me for debugging traces when I report a simple obvious bug and then tell me it’s not their fault, they should submit those bugs upstream, to Ruby, gem, or whatever. Whenever someone like me submits that bug to NetBeans they should mark it as duplicate of an existing open bug that points to the upstream bug. I would have followed that link and told the Ruby developers “wake up!”. As it is, I didn’t. It’s too much work for me.

    Reviewed by Daniel Magliola. Thank you!